]> git.uio.no Git - u/mrichter/AliRoot.git/blame - TRD/AliTRDseedV1.cxx
Small update (number of bins)
[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"
e4f2f73d 56#include "AliTRDrecoParam.h"
a076fc2f 57#include "AliTRDCommonParam.h"
d937ad7a 58
0906e73e 59#include "Cal/AliTRDCalPID.h"
d937ad7a 60#include "Cal/AliTRDCalROC.h"
61#include "Cal/AliTRDCalDet.h"
e4f2f73d 62
e4f2f73d 63ClassImp(AliTRDseedV1)
64
65//____________________________________________________________________
ae4e8b84 66AliTRDseedV1::AliTRDseedV1(Int_t det)
3e778975 67 :AliTRDtrackletBase()
3a039a31 68 ,fReconstructor(0x0)
ae4e8b84 69 ,fClusterIter(0x0)
e3cf3d02 70 ,fExB(0.)
71 ,fVD(0.)
72 ,fT0(0.)
73 ,fS2PRF(0.)
74 ,fDiffL(0.)
75 ,fDiffT(0.)
ae4e8b84 76 ,fClusterIdx(0)
3e778975 77 ,fN(0)
ae4e8b84 78 ,fDet(det)
b25a5e9e 79 ,fPt(0.)
bcb6fb78 80 ,fdX(0.)
e3cf3d02 81 ,fX0(0.)
82 ,fX(0.)
83 ,fY(0.)
84 ,fZ(0.)
85 ,fS2Y(0.)
86 ,fS2Z(0.)
87 ,fC(0.)
88 ,fChi2(0.)
e4f2f73d 89{
90 //
91 // Constructor
92 //
8d2bec9e 93 for(Int_t ic=kNclusters; ic--;) fIndexes[ic] = -1;
94 memset(fClusters, 0, kNclusters*sizeof(AliTRDcluster*));
dd8059a8 95 memset(fPad, 0, 3*sizeof(Float_t));
e3cf3d02 96 fYref[0] = 0.; fYref[1] = 0.;
97 fZref[0] = 0.; fZref[1] = 0.;
98 fYfit[0] = 0.; fYfit[1] = 0.;
99 fZfit[0] = 0.; fZfit[1] = 0.;
8d2bec9e 100 memset(fdEdx, 0, kNslices*sizeof(Float_t));
29b87567 101 for(int ispec=0; ispec<AliPID::kSPECIES; ispec++) fProb[ispec] = -1.;
e3cf3d02 102 fLabels[0]=-1; fLabels[1]=-1; // most freq MC labels
103 fLabels[2]=0; // number of different labels for tracklet
16cca13f 104 memset(fRefCov, 0, 7*sizeof(Double_t));
d937ad7a 105 // covariance matrix [diagonal]
106 // default sy = 200um and sz = 2.3 cm
107 fCov[0] = 4.e-4; fCov[1] = 0.; fCov[2] = 5.3;
f29f13a6 108 SetStandAlone(kFALSE);
e4f2f73d 109}
110
111//____________________________________________________________________
0906e73e 112AliTRDseedV1::AliTRDseedV1(const AliTRDseedV1 &ref)
3e778975 113 :AliTRDtrackletBase((AliTRDtrackletBase&)ref)
e3cf3d02 114 ,fReconstructor(0x0)
ae4e8b84 115 ,fClusterIter(0x0)
e3cf3d02 116 ,fExB(0.)
117 ,fVD(0.)
118 ,fT0(0.)
119 ,fS2PRF(0.)
120 ,fDiffL(0.)
121 ,fDiffT(0.)
ae4e8b84 122 ,fClusterIdx(0)
3e778975 123 ,fN(0)
e3cf3d02 124 ,fDet(-1)
b25a5e9e 125 ,fPt(0.)
e3cf3d02 126 ,fdX(0.)
127 ,fX0(0.)
128 ,fX(0.)
129 ,fY(0.)
130 ,fZ(0.)
131 ,fS2Y(0.)
132 ,fS2Z(0.)
133 ,fC(0.)
134 ,fChi2(0.)
e4f2f73d 135{
136 //
137 // Copy Constructor performing a deep copy
138 //
e3cf3d02 139 if(this != &ref){
140 ref.Copy(*this);
141 }
29b87567 142 SetBit(kOwner, kFALSE);
f29f13a6 143 SetStandAlone(ref.IsStandAlone());
fbb2ea06 144}
d9950a5a 145
0906e73e 146
e4f2f73d 147//____________________________________________________________________
148AliTRDseedV1& AliTRDseedV1::operator=(const AliTRDseedV1 &ref)
149{
150 //
151 // Assignment Operator using the copy function
152 //
153
29b87567 154 if(this != &ref){
155 ref.Copy(*this);
156 }
221ab7e0 157 SetBit(kOwner, kFALSE);
158
29b87567 159 return *this;
e4f2f73d 160}
161
162//____________________________________________________________________
163AliTRDseedV1::~AliTRDseedV1()
164{
165 //
166 // Destructor. The RecoParam object belongs to the underlying tracker.
167 //
168
29b87567 169 //printf("I-AliTRDseedV1::~AliTRDseedV1() : Owner[%s]\n", IsOwner()?"YES":"NO");
e4f2f73d 170
e3cf3d02 171 if(IsOwner()) {
8d2bec9e 172 for(int itb=0; itb<kNclusters; itb++){
29b87567 173 if(!fClusters[itb]) continue;
174 //AliInfo(Form("deleting c %p @ %d", fClusters[itb], itb));
175 delete fClusters[itb];
176 fClusters[itb] = 0x0;
177 }
e3cf3d02 178 }
e4f2f73d 179}
180
181//____________________________________________________________________
182void AliTRDseedV1::Copy(TObject &ref) const
183{
184 //
185 // Copy function
186 //
187
29b87567 188 //AliInfo("");
189 AliTRDseedV1 &target = (AliTRDseedV1 &)ref;
190
e3cf3d02 191 target.fReconstructor = fReconstructor;
ae4e8b84 192 target.fClusterIter = 0x0;
e3cf3d02 193 target.fExB = fExB;
194 target.fVD = fVD;
195 target.fT0 = fT0;
196 target.fS2PRF = fS2PRF;
197 target.fDiffL = fDiffL;
198 target.fDiffT = fDiffT;
ae4e8b84 199 target.fClusterIdx = 0;
3e778975 200 target.fN = fN;
ae4e8b84 201 target.fDet = fDet;
b25a5e9e 202 target.fPt = fPt;
29b87567 203 target.fdX = fdX;
e3cf3d02 204 target.fX0 = fX0;
205 target.fX = fX;
206 target.fY = fY;
207 target.fZ = fZ;
208 target.fS2Y = fS2Y;
209 target.fS2Z = fS2Z;
210 target.fC = fC;
211 target.fChi2 = fChi2;
29b87567 212
8d2bec9e 213 memcpy(target.fIndexes, fIndexes, kNclusters*sizeof(Int_t));
214 memcpy(target.fClusters, fClusters, kNclusters*sizeof(AliTRDcluster*));
dd8059a8 215 memcpy(target.fPad, fPad, 3*sizeof(Float_t));
e3cf3d02 216 target.fYref[0] = fYref[0]; target.fYref[1] = fYref[1];
217 target.fZref[0] = fZref[0]; target.fZref[1] = fZref[1];
218 target.fYfit[0] = fYfit[0]; target.fYfit[1] = fYfit[1];
219 target.fZfit[0] = fZfit[0]; target.fZfit[1] = fZfit[1];
8d2bec9e 220 memcpy(target.fdEdx, fdEdx, kNslices*sizeof(Float_t));
e3cf3d02 221 memcpy(target.fProb, fProb, AliPID::kSPECIES*sizeof(Float_t));
222 memcpy(target.fLabels, fLabels, 3*sizeof(Int_t));
16cca13f 223 memcpy(target.fRefCov, fRefCov, 7*sizeof(Double_t));
e3cf3d02 224 memcpy(target.fCov, fCov, 3*sizeof(Double_t));
29b87567 225
e3cf3d02 226 TObject::Copy(ref);
e4f2f73d 227}
228
0906e73e 229
230//____________________________________________________________
f3d3af1b 231Bool_t AliTRDseedV1::Init(AliTRDtrackV1 *track)
0906e73e 232{
233// Initialize this tracklet using the track information
234//
235// Parameters:
236// track - the TRD track used to initialize the tracklet
237//
238// Detailed description
239// The function sets the starting point and direction of the
240// tracklet according to the information from the TRD track.
241//
242// Caution
243// The TRD track has to be propagated to the beginning of the
244// chamber where the tracklet will be constructed
245//
246
29b87567 247 Double_t y, z;
248 if(!track->GetProlongation(fX0, y, z)) return kFALSE;
16cca13f 249 Update(track);
29b87567 250 return kTRUE;
0906e73e 251}
252
bcb6fb78 253
e3cf3d02 254//_____________________________________________________________________________
255void AliTRDseedV1::Reset()
256{
257 //
258 // Reset seed
259 //
260 fExB=0.;fVD=0.;fT0=0.;fS2PRF=0.;
261 fDiffL=0.;fDiffT=0.;
3e778975 262 fClusterIdx=0;
263 fN=0;
dd8059a8 264 fDet=-1;
b25a5e9e 265 fPt=0.;
e3cf3d02 266 fdX=0.;fX0=0.; fX=0.; fY=0.; fZ=0.;
267 fS2Y=0.; fS2Z=0.;
268 fC=0.; fChi2 = 0.;
269
8d2bec9e 270 for(Int_t ic=kNclusters; ic--;) fIndexes[ic] = -1;
271 memset(fClusters, 0, kNclusters*sizeof(AliTRDcluster*));
dd8059a8 272 memset(fPad, 0, 3*sizeof(Float_t));
e3cf3d02 273 fYref[0] = 0.; fYref[1] = 0.;
274 fZref[0] = 0.; fZref[1] = 0.;
275 fYfit[0] = 0.; fYfit[1] = 0.;
276 fZfit[0] = 0.; fZfit[1] = 0.;
8d2bec9e 277 memset(fdEdx, 0, kNslices*sizeof(Float_t));
e3cf3d02 278 for(int ispec=0; ispec<AliPID::kSPECIES; ispec++) fProb[ispec] = -1.;
279 fLabels[0]=-1; fLabels[1]=-1; // most freq MC labels
280 fLabels[2]=0; // number of different labels for tracklet
16cca13f 281 memset(fRefCov, 0, 7*sizeof(Double_t));
e3cf3d02 282 // covariance matrix [diagonal]
283 // default sy = 200um and sz = 2.3 cm
284 fCov[0] = 4.e-4; fCov[1] = 0.; fCov[2] = 5.3;
285}
286
b1957d3c 287//____________________________________________________________________
16cca13f 288void AliTRDseedV1::Update(const AliTRDtrackV1 *trk)
b1957d3c 289{
290 // update tracklet reference position from the TRD track
b1957d3c 291
e3cf3d02 292 Double_t fSnp = trk->GetSnp();
293 Double_t fTgl = trk->GetTgl();
b25a5e9e 294 fPt = trk->Pt();
1fd9389f 295 Double_t norm =1./TMath::Sqrt(1. - fSnp*fSnp);
296 fYref[1] = fSnp*norm;
297 fZref[1] = fTgl*norm;
b1957d3c 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
500851ab 458// #frac{dq}{dl} = #frac{q_{c}}{dx * #sqrt{1 + #(){#frac{dy}{dx}}^{2}_{fit} + #(){#frac{dz}{dx}}^{2}_{ref}}}
3ee48d6e 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//
0fa1a8ee 468//Begin_Html
469//<img src="TRD/trackletDQDT.gif">
470//End_Html
471// In the picture the energy loss measured on the tracklet as a function of drift time [left] and respectively
472// drift length [right] for different particle species is displayed.
3ee48d6e 473// Author : Alex Bercuci <A.Bercuci@gsi.de>
474//
475 Float_t dq = 0.;
5d401b45 476 // check whether both clusters are inside the chamber
477 Bool_t hasClusterInChamber = kFALSE;
478 if(fClusters[ic] && fClusters[ic]->IsInChamber()){
479 hasClusterInChamber = kTRUE;
1742f24c 480 dq += TMath::Abs(fClusters[ic]->GetQ());
5d401b45 481 }else if(fClusters[ic+kNtb] && fClusters[ic+kNtb]->IsInChamber()){
482 hasClusterInChamber = kTRUE;
483 dq += TMath::Abs(fClusters[ic+kNtb]->GetQ());
1742f24c 484 }
5d401b45 485 if(!hasClusterInChamber) return 0.;
0b433f72 486 if(dq<1.e-3) return 0.;
3ee48d6e 487
a2abcbc5 488 Double_t dx = fdX;
489 if(ic-1>=0 && ic+1<kNtb){
490 Float_t x2(0.), x1(0.);
5d401b45 491 // try to estimate upper radial position (find the cluster which is inside the chamber)
492 if(fClusters[ic-1] && fClusters[ic-1]->IsInChamber()) x2 = fClusters[ic-1]->GetX();
493 else if(fClusters[ic-1+kNtb] && fClusters[ic-1+kNtb]->IsInChamber()) x2 = fClusters[ic-1+kNtb]->GetX();
494 else if(fClusters[ic] && fClusters[ic]->IsInChamber()) x2 = fClusters[ic]->GetX()+fdX;
a2abcbc5 495 else x2 = fClusters[ic+kNtb]->GetX()+fdX;
5d401b45 496 // try to estimate lower radial position (find the cluster which is inside the chamber)
497 if(fClusters[ic+1] && fClusters[ic+1]->IsInChamber()) x1 = fClusters[ic+1]->GetX();
498 else if(fClusters[ic+1+kNtb] && fClusters[ic+1+kNtb]->IsInChamber()) x1 = fClusters[ic+1+kNtb]->GetX();
499 else if(fClusters[ic] && fClusters[ic]->IsInChamber()) x1 = fClusters[ic]->GetX()-fdX;
a2abcbc5 500 else x1 = fClusters[ic+kNtb]->GetX()-fdX;
501
502 dx = .5*(x2 - x1);
503 }
0b433f72 504 dx *= TMath::Sqrt(1. + fYfit[1]*fYfit[1] + fZref[1]*fZref[1]);
0b433f72 505 if(dl) (*dl) = dx;
506 return dq/dx;
bcb6fb78 507}
508
0b433f72 509//____________________________________________________________
510Float_t AliTRDseedV1::GetMomentum(Float_t *err) const
511{
512// Returns momentum of the track after update with the current tracklet as:
513// BEGIN_LATEX
514// p=#frac{1}{1/p_{t}} #sqrt{1+tgl^{2}}
515// END_LATEX
516// and optionally the momentum error (if err is not null).
517// The estimated variance of the momentum is given by:
518// BEGIN_LATEX
519// #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})
520// END_LATEX
521// which can be simplified to
522// BEGIN_LATEX
523// #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}
524// END_LATEX
525//
526
527 Double_t p = fPt*TMath::Sqrt(1.+fZref[1]*fZref[1]);
528 Double_t p2 = p*p;
529 Double_t tgl2 = fZref[1]*fZref[1];
530 Double_t pt2 = fPt*fPt;
531 if(err){
532 Double_t s2 =
533 p2*tgl2*pt2*pt2*fRefCov[4]
534 -2.*p2*fZref[1]*fPt*pt2*fRefCov[5]
535 +p2*pt2*fRefCov[6];
536 (*err) = TMath::Sqrt(s2);
537 }
538 return p;
539}
540
541
0906e73e 542//____________________________________________________________________
3e778975 543Float_t* AliTRDseedV1::GetProbability(Bool_t force)
0906e73e 544{
3e778975 545 if(!force) return &fProb[0];
546 if(!CookPID()) return 0x0;
547 return &fProb[0];
548}
549
550//____________________________________________________________
551Bool_t AliTRDseedV1::CookPID()
552{
0906e73e 553// Fill probability array for tracklet from the DB.
554//
555// Parameters
556//
557// Output
558// returns pointer to the probability array and 0x0 if missing DB access
559//
2a3191bb 560// Retrieve PID probabilities for e+-, mu+-, K+-, pi+- and p+- from the DB according to tracklet information:
561// - estimated momentum at tracklet reference point
562// - dE/dx measurements
563// - tracklet length
564// - TRD layer
565// According to the steering settings specified in the reconstruction one of the following methods are used
566// - Neural Network [default] - option "nn"
567// - 2D Likelihood - option "!nn"
0906e73e 568
0906e73e 569 AliTRDcalibDB *calibration = AliTRDcalibDB::Instance();
570 if (!calibration) {
571 AliError("No access to calibration data");
3e778975 572 return kFALSE;
0906e73e 573 }
574
3a039a31 575 if (!fReconstructor) {
576 AliError("Reconstructor not set.");
3e778975 577 return kFALSE;
4ba1d6ae 578 }
579
0906e73e 580 // Retrieve the CDB container class with the parametric detector response
3a039a31 581 const AliTRDCalPID *pd = calibration->GetPIDObject(fReconstructor->GetPIDMethod());
0906e73e 582 if (!pd) {
583 AliError("No access to AliTRDCalPID object");
3e778975 584 return kFALSE;
0906e73e 585 }
29b87567 586 //AliInfo(Form("Method[%d] : %s", fReconstructor->GetRecoParam() ->GetPIDMethod(), pd->IsA()->GetName()));
10f75631 587
29b87567 588 // calculate tracklet length TO DO
0906e73e 589 Float_t length = (AliTRDgeometry::AmThick() + AliTRDgeometry::DrThick());
590 /// TMath::Sqrt((1.0 - fSnp[iPlane]*fSnp[iPlane]) / (1.0 + fTgl[iPlane]*fTgl[iPlane]));
591
592 //calculate dE/dx
3a039a31 593 CookdEdx(fReconstructor->GetNdEdxSlices());
0906e73e 594
595 // Sets the a priori probabilities
596 for(int ispec=0; ispec<AliPID::kSPECIES; ispec++) {
b25a5e9e 597 fProb[ispec] = pd->GetProbability(ispec, GetMomentum(), &fdEdx[0], length, GetPlane());
0906e73e 598 }
599
3e778975 600 return kTRUE;
0906e73e 601}
602
e4f2f73d 603//____________________________________________________________________
604Float_t AliTRDseedV1::GetQuality(Bool_t kZcorr) const
605{
606 //
607 // Returns a quality measurement of the current seed
608 //
609
dd8059a8 610 Float_t zcorr = kZcorr ? GetTilt() * (fZfit[0] - fZref[0]) : 0.;
29b87567 611 return
3e778975 612 .5 * TMath::Abs(18.0 - GetN())
29b87567 613 + 10.* TMath::Abs(fYfit[1] - fYref[1])
614 + 5. * TMath::Abs(fYfit[0] - fYref[0] + zcorr)
dd8059a8 615 + 2. * TMath::Abs(fZfit[0] - fZref[0]) / GetPadLength();
e4f2f73d 616}
617
0906e73e 618//____________________________________________________________________
d937ad7a 619void AliTRDseedV1::GetCovAt(Double_t x, Double_t *cov) const
0906e73e 620{
d937ad7a 621// Computes covariance in the y-z plane at radial point x (in tracking coordinates)
622// and returns the results in the preallocated array cov[3] as :
623// cov[0] = Var(y)
624// cov[1] = Cov(yz)
625// cov[2] = Var(z)
626//
627// Details
628//
629// For the linear transformation
630// BEGIN_LATEX
631// Y = T_{x} X^{T}
632// END_LATEX
633// The error propagation has the general form
634// BEGIN_LATEX
635// C_{Y} = T_{x} C_{X} T_{x}^{T}
636// END_LATEX
637// We apply this formula 2 times. First to calculate the covariance of the tracklet
638// at point x we consider:
639// BEGIN_LATEX
640// T_{x} = (1 x); X=(y0 dy/dx); C_{X}=#(){#splitline{Var(y0) Cov(y0, dy/dx)}{Cov(y0, dy/dx) Var(dy/dx)}}
641// END_LATEX
642// and secondly to take into account the tilt angle
643// BEGIN_LATEX
644// T_{#alpha} = #(){#splitline{cos(#alpha) __ sin(#alpha)}{-sin(#alpha) __ cos(#alpha)}}; X=(y z); C_{X}=#(){#splitline{Var(y) 0}{0 Var(z)}}
645// END_LATEX
646//
647// using simple trigonometrics one can write for this last case
648// BEGIN_LATEX
649// 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})}}
650// END_LATEX
651// which can be aproximated for small alphas (2 deg) with
652// BEGIN_LATEX
653// 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}}}
654// END_LATEX
655//
656// before applying the tilt rotation we also apply systematic uncertainties to the tracklet
657// position which can be tunned from outside via the AliTRDrecoParam::SetSysCovMatrix(). They might
658// account for extra misalignment/miscalibration uncertainties.
659//
660// Author :
661// Alex Bercuci <A.Bercuci@gsi.de>
662// Date : Jan 8th 2009
663//
b1957d3c 664
665
d937ad7a 666 Double_t xr = fX0-x;
667 Double_t sy2 = fCov[0] +2.*xr*fCov[1] + xr*xr*fCov[2];
b72f4eaf 668 Double_t sz2 = fS2Z;
669 //GetPadLength()*GetPadLength()/12.;
0906e73e 670
d937ad7a 671 // insert systematic uncertainties
bb2db46c 672 if(fReconstructor){
673 Double_t sys[15]; memset(sys, 0, 15*sizeof(Double_t));
674 fReconstructor->GetRecoParam()->GetSysCovMatrix(sys);
675 sy2 += sys[0];
676 sz2 += sys[1];
677 }
d937ad7a 678 // rotate covariance matrix
dd8059a8 679 Double_t t2 = GetTilt()*GetTilt();
d937ad7a 680 Double_t correction = 1./(1. + t2);
681 cov[0] = (sy2+t2*sz2)*correction;
dd8059a8 682 cov[1] = GetTilt()*(sz2 - sy2)*correction;
d937ad7a 683 cov[2] = (t2*sy2+sz2)*correction;
b72f4eaf 684
685 //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 686}
eb38ed55 687
bb2db46c 688//____________________________________________________________
689Double_t AliTRDseedV1::GetCovSqrt(Double_t *c, Double_t *d)
690{
691// Helper function to calculate the square root of the covariance matrix.
692// The input matrix is stored in the vector c and the result in the vector d.
41b7c7b6 693// Both arrays have to be initialized by the user with at least 3 elements. Return negative in case of failure.
bb2db46c 694//
ec3f0161 695// For calculating the square root of the symmetric matrix c
696// the following relation is used:
bb2db46c 697// BEGIN_LATEX
ec3f0161 698// C^{1/2} = VD^{1/2}V^{-1}
bb2db46c 699// END_LATEX
41b7c7b6 700// with V being the matrix with the n eigenvectors as columns.
ec3f0161 701// In case C is symmetric the followings are true:
702// - matrix D is diagonal with the diagonal given by the eigenvalues of C
41b7c7b6 703// - V = V^{-1}
bb2db46c 704//
705// Author A.Bercuci <A.Bercuci@gsi.de>
706// Date Mar 19 2009
707
41b7c7b6 708 Double_t L[2], // eigenvalues
709 V[3]; // eigenvectors
bb2db46c 710 // the secular equation and its solution :
711 // (c[0]-L)(c[2]-L)-c[1]^2 = 0
712 // L^2 - L*Tr(c)+DET(c) = 0
713 // L12 = [Tr(c) +- sqrt(Tr(c)^2-4*DET(c))]/2
714 Double_t Tr = c[0]+c[2], // trace
715 DET = c[0]*c[2]-c[1]*c[1]; // determinant
41b7c7b6 716 if(TMath::Abs(DET)<1.e-20) return -1.;
bb2db46c 717 Double_t DD = TMath::Sqrt(Tr*Tr - 4*DET);
718 L[0] = .5*(Tr + DD);
719 L[1] = .5*(Tr - DD);
41b7c7b6 720 if(L[0]<0. || L[1]<0.) return -1.;
721
722 // the sym V matrix
723 // | v00 v10|
724 // | v10 v11|
725 Double_t tmp = (L[0]-c[0])/c[1];
726 V[0] = TMath::Sqrt(1./(tmp*tmp+1));
727 V[1] = tmp*V[0];
728 V[2] = V[1]*c[1]/(L[1]-c[2]);
729 // the VD^{1/2}V is:
730 L[0] = TMath::Sqrt(L[0]); L[1] = TMath::Sqrt(L[1]);
731 d[0] = V[0]*V[0]*L[0]+V[1]*V[1]*L[1];
732 d[1] = V[0]*V[1]*L[0]+V[1]*V[2]*L[1];
733 d[2] = V[1]*V[1]*L[0]+V[2]*V[2]*L[1];
bb2db46c 734
735 return 1.;
736}
737
738//____________________________________________________________
739Double_t AliTRDseedV1::GetCovInv(Double_t *c, Double_t *d)
740{
741// Helper function to calculate the inverse of the covariance matrix.
742// The input matrix is stored in the vector c and the result in the vector d.
743// Both arrays have to be initialized by the user with at least 3 elements
744// The return value is the determinant or 0 in case of singularity.
745//
746// Author A.Bercuci <A.Bercuci@gsi.de>
747// Date Mar 19 2009
748
749 Double_t Det = c[0]*c[2] - c[1]*c[1];
750 if(TMath::Abs(Det)<1.e-20) return 0.;
751 Double_t InvDet = 1./Det;
752 d[0] = c[2]*InvDet;
753 d[1] =-c[1]*InvDet;
754 d[2] = c[0]*InvDet;
755 return Det;
756}
0906e73e 757
b72f4eaf 758//____________________________________________________________________
759UShort_t AliTRDseedV1::GetVolumeId() const
760{
761 Int_t ic=0;
762 while(ic<kNclusters && !fClusters[ic]) ic++;
763 return fClusters[ic] ? fClusters[ic]->GetVolumeId() : 0;
764}
765
766
d937ad7a 767//____________________________________________________________________
e3cf3d02 768void AliTRDseedV1::Calibrate()
d937ad7a 769{
e3cf3d02 770// Retrieve calibration and position parameters from OCDB.
771// The following information are used
d937ad7a 772// - detector index
e3cf3d02 773// - column and row position of first attached cluster. If no clusters are attached
774// to the tracklet a random central chamber position (c=70, r=7) will be used.
775//
776// The following information is cached in the tracklet
777// t0 (trigger delay)
778// drift velocity
779// PRF width
780// omega*tau = tg(a_L)
781// diffusion coefficients (longitudinal and transversal)
d937ad7a 782//
783// Author :
784// Alex Bercuci <A.Bercuci@gsi.de>
785// Date : Jan 8th 2009
786//
eb38ed55 787
d937ad7a 788 AliCDBManager *cdb = AliCDBManager::Instance();
789 if(cdb->GetRun() < 0){
790 AliError("OCDB manager not properly initialized");
791 return;
792 }
0906e73e 793
e3cf3d02 794 AliTRDcalibDB *calib = AliTRDcalibDB::Instance();
795 AliTRDCalROC *vdROC = calib->GetVdriftROC(fDet),
796 *t0ROC = calib->GetT0ROC(fDet);;
797 const AliTRDCalDet *vdDet = calib->GetVdriftDet();
798 const AliTRDCalDet *t0Det = calib->GetT0Det();
d937ad7a 799
800 Int_t col = 70, row = 7;
801 AliTRDcluster **c = &fClusters[0];
3e778975 802 if(GetN()){
d937ad7a 803 Int_t ic = 0;
8d2bec9e 804 while (ic<kNclusters && !(*c)){ic++; c++;}
d937ad7a 805 if(*c){
806 col = (*c)->GetPadCol();
807 row = (*c)->GetPadRow();
808 }
809 }
3a039a31 810
e3cf3d02 811 fT0 = t0Det->GetValue(fDet) + t0ROC->GetValue(col,row);
812 fVD = vdDet->GetValue(fDet) * vdROC->GetValue(col, row);
813 fS2PRF = calib->GetPRFWidth(fDet, col, row); fS2PRF *= fS2PRF;
814 fExB = AliTRDCommonParam::Instance()->GetOmegaTau(fVD);
815 AliTRDCommonParam::Instance()->GetDiffCoeff(fDiffL,
816 fDiffT, fVD);
817 SetBit(kCalib, kTRUE);
0906e73e 818}
819
0906e73e 820//____________________________________________________________________
29b87567 821void AliTRDseedV1::SetOwner()
0906e73e 822{
29b87567 823 //AliInfo(Form("own [%s] fOwner[%s]", own?"YES":"NO", fOwner?"YES":"NO"));
824
825 if(TestBit(kOwner)) return;
8d2bec9e 826 for(int ic=0; ic<kNclusters; ic++){
29b87567 827 if(!fClusters[ic]) continue;
828 fClusters[ic] = new AliTRDcluster(*fClusters[ic]);
829 }
830 SetBit(kOwner);
0906e73e 831}
832
eb2b4f91 833//____________________________________________________________
834void AliTRDseedV1::SetPadPlane(AliTRDpadPlane *p)
835{
836// Shortcut method to initialize pad geometry.
837 if(!p) return;
838 SetTilt(TMath::Tan(TMath::DegToRad()*p->GetTiltingAngle()));
839 SetPadLength(p->GetLengthIPad());
840 SetPadWidth(p->GetWidthIPad());
841}
842
843
e4f2f73d 844//____________________________________________________________________
b1957d3c 845Bool_t AliTRDseedV1::AttachClusters(AliTRDtrackingChamber *chamber, Bool_t tilt)
e4f2f73d 846{
1fd9389f 847//
848// Projective algorithm to attach clusters to seeding tracklets. The following steps are performed :
849// 1. Collapse x coordinate for the full detector plane
850// 2. truncated mean on y (r-phi) direction
851// 3. purge clusters
852// 4. truncated mean on z direction
853// 5. purge clusters
854//
855// Parameters
856// - chamber : pointer to tracking chamber container used to search the tracklet
857// - tilt : switch for tilt correction during road building [default true]
858// Output
859// - true : if tracklet found successfully. Failure can happend because of the following:
860// -
861// Detailed description
862//
863// We start up by defining the track direction in the xy plane and roads. The roads are calculated based
8a7ff53c 864// on tracking information (variance in the r-phi direction) and estimated variance of the standard
865// clusters (see AliTRDcluster::SetSigmaY2()) corrected for tilt (see GetCovAt()). From this the road is
866// BEGIN_LATEX
500851ab 867// r_{y} = 3*#sqrt{12*(#sigma^{2}_{Trk}(y) + #frac{#sigma^{2}_{cl}(y) + tg^{2}(#alpha_{L})#sigma^{2}_{cl}(z)}{1+tg^{2}(#alpha_{L})})}
8a7ff53c 868// r_{z} = 1.5*L_{pad}
869// END_LATEX
1fd9389f 870//
4b755889 871// Author : Alexandru Bercuci <A.Bercuci@gsi.de>
872// Debug : level >3
1fd9389f 873
b1957d3c 874 Bool_t kPRINT = kFALSE;
29b87567 875 if(!fReconstructor->GetRecoParam() ){
876 AliError("Seed can not be used without a valid RecoParam.");
877 return kFALSE;
878 }
b1957d3c 879 // Initialize reco params for this tracklet
880 // 1. first time bin in the drift region
a2abcbc5 881 Int_t t0 = 14;
b1957d3c 882 Int_t kClmin = Int_t(fReconstructor->GetRecoParam() ->GetFindableClusters()*AliTRDtrackerV1::GetNTimeBins());
29b87567 883
8a7ff53c 884 Double_t s2yTrk= fRefCov[0],
885 s2yCl = 0.,
886 s2zCl = GetPadLength()*GetPadLength()/12.,
887 syRef = TMath::Sqrt(s2yTrk),
888 t2 = GetTilt()*GetTilt();
29b87567 889 //define roads
8a7ff53c 890 Double_t kroady = 1., //fReconstructor->GetRecoParam() ->GetRoad1y();
891 kroadz = GetPadLength() * 1.5 + 1.;
892 // define probing cluster (the perfect cluster) and default calibration
893 Short_t sig[] = {0, 0, 10, 30, 10, 0,0};
894 AliTRDcluster cp(fDet, 6, 75, 0, sig, 0);
d07eec70 895 if(fReconstructor->IsHLT())cp.SetRPhiMethod(AliTRDcluster::kCOG);
8a7ff53c 896 Calibrate();
897
b1957d3c 898 if(kPRINT) printf("AttachClusters() sy[%f] road[%f]\n", syRef, kroady);
29b87567 899
900 // working variables
b1957d3c 901 const Int_t kNrows = 16;
4b755889 902 const Int_t kNcls = 3*kNclusters; // buffer size
903 AliTRDcluster *clst[kNrows][kNcls];
904 Double_t cond[4], dx, dy, yt, zt, yres[kNrows][kNcls];
905 Int_t idxs[kNrows][kNcls], ncl[kNrows], ncls = 0;
b1957d3c 906 memset(ncl, 0, kNrows*sizeof(Int_t));
4b755889 907 memset(yres, 0, kNrows*kNcls*sizeof(Double_t));
908 memset(clst, 0, kNrows*kNcls*sizeof(AliTRDcluster*));
b1957d3c 909
29b87567 910 // Do cluster projection
b1957d3c 911 AliTRDcluster *c = 0x0;
29b87567 912 AliTRDchamberTimeBin *layer = 0x0;
b1957d3c 913 Bool_t kBUFFER = kFALSE;
4b755889 914 for (Int_t it = 0; it < kNtb; it++) {
b1957d3c 915 if(!(layer = chamber->GetTB(it))) continue;
29b87567 916 if(!Int_t(*layer)) continue;
8a7ff53c 917 // get track projection at layers position
b1957d3c 918 dx = fX0 - layer->GetX();
919 yt = fYref[0] - fYref[1] * dx;
920 zt = fZref[0] - fZref[1] * dx;
8a7ff53c 921 // get standard cluster error corrected for tilt
922 cp.SetLocalTimeBin(it);
923 cp.SetSigmaY2(0.02, fDiffT, fExB, dx, -1./*zt*/, fYref[1]);
924 s2yCl = (cp.GetSigmaY2() + t2*s2zCl)/(1.+t2);
925 // get estimated road
926 kroady = 3.*TMath::Sqrt(12.*(s2yTrk + s2yCl));
927
928 if(kPRINT) printf(" %2d dx[%f] yt[%f] zt[%f] sT[um]=%6.2f sy[um]=%6.2f syTilt[um]=%6.2f yRoad[mm]=%f\n", it, dx, yt, zt, 1.e4*TMath::Sqrt(s2yTrk), 1.e4*TMath::Sqrt(cp.GetSigmaY2()), 1.e4*TMath::Sqrt(s2yCl), 1.e1*kroady);
b1957d3c 929
8a7ff53c 930 // select clusters
b1957d3c 931 cond[0] = yt; cond[2] = kroady;
932 cond[1] = zt; cond[3] = kroadz;
933 Int_t n=0, idx[6];
934 layer->GetClusters(cond, idx, n, 6);
935 for(Int_t ic = n; ic--;){
936 c = (*layer)[idx[ic]];
937 dy = yt - c->GetY();
dd8059a8 938 dy += tilt ? GetTilt() * (c->GetZ() - zt) : 0.;
b1957d3c 939 // select clusters on a 3 sigmaKalman level
940/* if(tilt && TMath::Abs(dy) > 3.*syRef){
941 printf("too large !!!\n");
942 continue;
943 }*/
944 Int_t r = c->GetPadRow();
945 if(kPRINT) printf("\t\t%d dy[%f] yc[%f] r[%d]\n", ic, TMath::Abs(dy), c->GetY(), r);
946 clst[r][ncl[r]] = c;
947 idxs[r][ncl[r]] = idx[ic];
948 yres[r][ncl[r]] = dy;
949 ncl[r]++; ncls++;
950
4b755889 951 if(ncl[r] >= kNcls) {
952 AliWarning(Form("Cluster candidates reached buffer limit %d. Some may be lost.", kNcls));
b1957d3c 953 kBUFFER = kTRUE;
29b87567 954 break;
955 }
956 }
b1957d3c 957 if(kBUFFER) break;
29b87567 958 }
b1957d3c 959 if(kPRINT) printf("Found %d clusters\n", ncls);
960 if(ncls<kClmin) return kFALSE;
961
962 // analyze each row individualy
963 Double_t mean, syDis;
964 Int_t nrow[] = {0, 0, 0}, nr = 0, lr=-1;
965 for(Int_t ir=kNrows; ir--;){
966 if(!(ncl[ir])) continue;
967 if(lr>0 && lr-ir != 1){
968 if(kPRINT) printf("W - gap in rows attached !!\n");
29b87567 969 }
b1957d3c 970 if(kPRINT) printf("\tir[%d] lr[%d] n[%d]\n", ir, lr, ncl[ir]);
971 // Evaluate truncated mean on the y direction
972 if(ncl[ir] > 3) AliMathBase::EvaluateUni(ncl[ir], yres[ir], mean, syDis, Int_t(ncl[ir]*.8));
973 else {
974 mean = 0.; syDis = 0.;
8a7ff53c 975 continue;
b1957d3c 976 }
977
4b755889 978 if(fReconstructor->GetStreamLevel(AliTRDReconstructor::kTracker) > 3){
979 TTreeSRedirector &cstreamer = *fReconstructor->GetDebugStream(AliTRDReconstructor::kTracker);
bb5265c9 980 TVectorD vdy(ncl[ir], yres[ir]);
21a6e3ac 981 UChar_t stat(0);
982 if(IsKink()) SETBIT(stat, 0);
983 if(IsStandAlone()) SETBIT(stat, 1);
4b755889 984 cstreamer << "AttachClusters"
21a6e3ac 985 << "stat=" << stat
986 << "det=" << fDet
987 << "pt=" << fPt
988 << "s2y=" << s2yTrk
bb5265c9 989 << "dy=" << &vdy
21a6e3ac 990 << "m=" << mean
991 << "s=" << syDis
4b755889 992 << "\n";
993 }
994
b1957d3c 995 // TODO check mean and sigma agains cluster resolution !!
8a7ff53c 996 if(kPRINT) printf("\tr[%2d] m[%f %5.3fsigma] s[%f]\n", ir, mean, TMath::Abs(mean/syDis), syDis);
b1957d3c 997 // select clusters on a 3 sigmaDistr level
998 Bool_t kFOUND = kFALSE;
999 for(Int_t ic = ncl[ir]; ic--;){
1000 if(yres[ir][ic] - mean > 3. * syDis){
1001 clst[ir][ic] = 0x0; continue;
1002 }
1003 nrow[nr]++; kFOUND = kTRUE;
1004 }
1005 // exit loop
1006 if(kFOUND) nr++;
1007 lr = ir; if(nr>=3) break;
29b87567 1008 }
b1957d3c 1009 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]);
1010
1011 // classify cluster rows
1012 Int_t row = -1;
1013 switch(nr){
1014 case 1:
1015 row = lr;
1016 break;
1017 case 2:
1018 SetBit(kRowCross, kTRUE); // mark pad row crossing
1019 if(nrow[0] > nrow[1]){ row = lr+1; lr = -1;}
1020 else{
1021 row = lr; lr = 1;
1022 nrow[2] = nrow[1];
1023 nrow[1] = nrow[0];
1024 nrow[0] = nrow[2];
29b87567 1025 }
b1957d3c 1026 break;
1027 case 3:
1028 SetBit(kRowCross, kTRUE); // mark pad row crossing
1029 break;
29b87567 1030 }
b1957d3c 1031 if(kPRINT) printf("\trow[%d] n[%d]\n\n", row, nrow[0]);
1032 if(row<0) return kFALSE;
29b87567 1033
b1957d3c 1034 // Select and store clusters
1035 // We should consider here :
1036 // 1. How far is the chamber boundary
1037 // 2. How big is the mean
3e778975 1038 Int_t n = 0;
b1957d3c 1039 for (Int_t ir = 0; ir < nr; ir++) {
1040 Int_t jr = row + ir*lr;
1041 if(kPRINT) printf("\tattach %d clusters for row %d\n", ncl[jr], jr);
1042 for (Int_t ic = 0; ic < ncl[jr]; ic++) {
1043 if(!(c = clst[jr][ic])) continue;
1044 Int_t it = c->GetPadTime();
1045 // TODO proper indexing of clusters !!
e3cf3d02 1046 fIndexes[it+kNtb*ir] = chamber->GetTB(it)->GetGlobalIndex(idxs[jr][ic]);
1047 fClusters[it+kNtb*ir] = c;
29b87567 1048
b1957d3c 1049 //printf("\tid[%2d] it[%d] idx[%d]\n", ic, it, fIndexes[it]);
1050
3e778975 1051 n++;
b1957d3c 1052 }
1053 }
1054
29b87567 1055 // number of minimum numbers of clusters expected for the tracklet
3e778975 1056 if (n < kClmin){
1057 //AliWarning(Form("Not enough clusters to fit the tracklet %d [%d].", n, kClmin));
e4f2f73d 1058 return kFALSE;
1059 }
3e778975 1060 SetN(n);
0906e73e 1061
e3cf3d02 1062 // Load calibration parameters for this tracklet
1063 Calibrate();
b1957d3c 1064
1065 // calculate dx for time bins in the drift region (calibration aware)
a2abcbc5 1066 Float_t x[2] = {0.,0.}; Int_t tb[2]={0,0};
1067 for (Int_t it = t0, irp=0; irp<2 && it < AliTRDtrackerV1::GetNTimeBins(); it++) {
b1957d3c 1068 if(!fClusters[it]) continue;
1069 x[irp] = fClusters[it]->GetX();
a2abcbc5 1070 tb[irp] = fClusters[it]->GetLocalTimeBin();
b1957d3c 1071 irp++;
e3cf3d02 1072 }
d86ed84c 1073 Int_t dtb = tb[1] - tb[0];
1074 fdX = dtb ? (x[0] - x[1]) / dtb : 0.15;
29b87567 1075 return kTRUE;
e4f2f73d 1076}
1077
03cef9b2 1078//____________________________________________________________
1079void AliTRDseedV1::Bootstrap(const AliTRDReconstructor *rec)
1080{
1081// Fill in all derived information. It has to be called after recovery from file or HLT.
1082// The primitive data are
1083// - list of clusters
1084// - detector (as the detector will be removed from clusters)
1085// - position of anode wire (fX0) - temporary
1086// - track reference position and direction
1087// - momentum of the track
1088// - time bin length [cm]
1089//
1090// A.Bercuci <A.Bercuci@gsi.de> Oct 30th 2008
1091//
1092 fReconstructor = rec;
1093 AliTRDgeometry g;
1094 AliTRDpadPlane *pp = g.GetPadPlane(fDet);
dd8059a8 1095 fPad[0] = pp->GetLengthIPad();
1096 fPad[1] = pp->GetWidthIPad();
1097 fPad[3] = TMath::Tan(TMath::DegToRad()*pp->GetTiltingAngle());
e3cf3d02 1098 //fSnp = fYref[1]/TMath::Sqrt(1+fYref[1]*fYref[1]);
1099 //fTgl = fZref[1];
3e778975 1100 Int_t n = 0, nshare = 0, nused = 0;
03cef9b2 1101 AliTRDcluster **cit = &fClusters[0];
8d2bec9e 1102 for(Int_t ic = kNclusters; ic--; cit++){
03cef9b2 1103 if(!(*cit)) return;
3e778975 1104 n++;
1105 if((*cit)->IsShared()) nshare++;
1106 if((*cit)->IsUsed()) nused++;
03cef9b2 1107 }
3e778975 1108 SetN(n); SetNUsed(nused); SetNShared(nshare);
e3cf3d02 1109 Fit();
03cef9b2 1110 CookLabels();
1111 GetProbability();
1112}
1113
1114
e4f2f73d 1115//____________________________________________________________________
b72f4eaf 1116Bool_t AliTRDseedV1::Fit(Bool_t tilt, Bool_t zcorr)
e4f2f73d 1117{
16cca13f 1118//
1119// Linear fit of the clusters attached to the tracklet
1120//
1121// Parameters :
1122// - tilt : switch for tilt pad correction of cluster y position based on
1123// the z, dzdx info from outside [default false].
1124// - zcorr : switch for using z information to correct for anisochronity
1fd9389f 1125// and a finner error parameterization estimation [default false]
16cca13f 1126// Output :
1127// True if successful
1128//
1129// Detailed description
1130//
1131// Fit in the xy plane
1132//
1fd9389f 1133// The fit is performed to estimate the y position of the tracklet and the track
1134// angle in the bending plane. The clusters are represented in the chamber coordinate
1135// system (with respect to the anode wire - see AliTRDtrackerV1::FollowBackProlongation()
1136// on how this is set). The x and y position of the cluster and also their variances
1137// are known from clusterizer level (see AliTRDcluster::GetXloc(), AliTRDcluster::GetYloc(),
1138// AliTRDcluster::GetSX() and AliTRDcluster::GetSY()).
1139// If gaussian approximation is used to calculate y coordinate of the cluster the position
1140// is recalculated taking into account the track angle. The general formula to calculate the
1141// error of cluster position in the gaussian approximation taking into account diffusion and track
1142// inclination is given for TRD by:
1143// BEGIN_LATEX
1144// #sigma^{2}_{y} = #sigma^{2}_{PRF} + #frac{x#delta_{t}^{2}}{(1+tg(#alpha_{L}))^{2}} + #frac{x^{2}tg^{2}(#phi-#alpha_{L})tg^{2}(#alpha_{L})}{12}
1145// END_LATEX
1146//
1147// Since errors are calculated only in the y directions, radial errors (x direction) are mapped to y
1148// by projection i.e.
1149// BEGIN_LATEX
1150// #sigma_{x|y} = tg(#phi) #sigma_{x}
1151// END_LATEX
1152// and also by the lorentz angle correction
1153//
1154// Fit in the xz plane
1155//
1156// The "fit" is performed to estimate the radial position (x direction) where pad row cross happens.
1157// If no pad row crossing the z position is taken from geometry and radial position is taken from the xy
1158// fit (see below).
1159//
1160// There are two methods to estimate the radial position of the pad row cross:
1161// 1. leading cluster radial position : Here the lower part of the tracklet is considered and the last
1162// cluster registered (at radial x0) on this segment is chosen to mark the pad row crossing. The error
1163// of the z estimate is given by :
1164// BEGIN_LATEX
1165// #sigma_{z} = tg(#theta) #Delta x_{x_{0}}/12
1166// END_LATEX
1167// The systematic errors for this estimation are generated by the following sources:
1168// - no charge sharing between pad rows is considered (sharp cross)
1169// - missing cluster at row cross (noise peak-up, under-threshold signal etc.).
1170//
1171// 2. charge fit over the crossing point : Here the full energy deposit along the tracklet is considered
1172// to estimate the position of the crossing by a fit in the qx plane. The errors in the q directions are
1173// parameterized as s_q = q^2. The systematic errors for this estimation are generated by the following sources:
1174// - no general model for the qx dependence
1175// - physical fluctuations of the charge deposit
1176// - gain calibration dependence
1177//
1178// Estimation of the radial position of the tracklet
16cca13f 1179//
1fd9389f 1180// For pad row cross the radial position is taken from the xz fit (see above). Otherwise it is taken as the
1181// interpolation point of the tracklet i.e. the point where the error in y of the fit is minimum. The error
1182// in the y direction of the tracklet is (see AliTRDseedV1::GetCovAt()):
1183// BEGIN_LATEX
1184// #sigma_{y} = #sigma^{2}_{y_{0}} + 2xcov(y_{0}, dy/dx) + #sigma^{2}_{dy/dx}
1185// END_LATEX
1186// and thus the radial position is:
1187// BEGIN_LATEX
1188// x = - cov(y_{0}, dy/dx)/#sigma^{2}_{dy/dx}
1189// END_LATEX
1190//
1191// Estimation of tracklet position error
1192//
1193// The error in y direction is the error of the linear fit at the radial position of the tracklet while in the z
1194// direction is given by the cluster error or pad row cross error. In case of no pad row cross this is given by:
1195// BEGIN_LATEX
1196// #sigma_{y} = #sigma^{2}_{y_{0}} - 2cov^{2}(y_{0}, dy/dx)/#sigma^{2}_{dy/dx} + #sigma^{2}_{dy/dx}
1197// #sigma_{z} = Pad_{length}/12
1198// END_LATEX
1199// For pad row cross the full error is calculated at the radial position of the crossing (see above) and the error
1200// in z by the width of the crossing region - being a matter of parameterization.
1201// BEGIN_LATEX
1202// #sigma_{z} = tg(#theta) #Delta x_{x_{0}}/12
1203// END_LATEX
1204// In case of no tilt correction (default in the barrel tracking) the tilt is taken into account by the rotation of
1205// the covariance matrix. See AliTRDseedV1::GetCovAt() for details.
1206//
1207// Author
1208// A.Bercuci <A.Bercuci@gsi.de>
e4f2f73d 1209
b72f4eaf 1210 if(!IsCalibrated()) Calibrate();
e3cf3d02 1211
29b87567 1212 const Int_t kClmin = 8;
010d62b0 1213
2f7d6ac8 1214 // get track direction
1215 Double_t y0 = fYref[0];
1216 Double_t dydx = fYref[1];
1217 Double_t z0 = fZref[0];
1218 Double_t dzdx = fZref[1];
1219 Double_t yt, zt;
ae4e8b84 1220
b1957d3c 1221 //AliTRDtrackerV1::AliTRDLeastSquare fitterZ;
24d8660e 1222 TLinearFitter fitterY(1, "pol1");
b72f4eaf 1223 TLinearFitter fitterZ(1, "pol1");
ae4e8b84 1224
29b87567 1225 // book cluster information
8d2bec9e 1226 Double_t qc[kNclusters], xc[kNclusters], yc[kNclusters], zc[kNclusters], sy[kNclusters];
e3cf3d02 1227
dd8059a8 1228 Int_t n = 0;
9eb2d46c 1229 AliTRDcluster *c=0x0, **jc = &fClusters[0];
9eb2d46c 1230 for (Int_t ic=0; ic<kNtb; ic++, ++jc) {
29b87567 1231 xc[ic] = -1.;
1232 yc[ic] = 999.;
1233 zc[ic] = 999.;
1234 sy[ic] = 0.;
9eb2d46c 1235 if(!(c = (*jc))) continue;
29b87567 1236 if(!c->IsInChamber()) continue;
9462866a 1237
29b87567 1238 Float_t w = 1.;
1239 if(c->GetNPads()>4) w = .5;
1240 if(c->GetNPads()>5) w = .2;
010d62b0 1241
1fd9389f 1242 // cluster charge
dd8059a8 1243 qc[n] = TMath::Abs(c->GetQ());
1fd9389f 1244 // pad row of leading
1245
b72f4eaf 1246 // Radial cluster position
e3cf3d02 1247 //Int_t jc = TMath::Max(fN-3, 0);
1248 //xc[fN] = c->GetXloc(fT0, fVD, &qc[jc], &xc[jc]/*, z0 - c->GetX()*dzdx*/);
b72f4eaf 1249 xc[n] = fX0 - c->GetX();
1250
1fd9389f 1251 // extrapolated track to cluster position
dd8059a8 1252 yt = y0 - xc[n]*dydx;
dd8059a8 1253 zt = z0 - xc[n]*dzdx;
1fd9389f 1254
1255 // Recalculate cluster error based on tracking information
1256 c->SetSigmaY2(fS2PRF, fDiffT, fExB, xc[n], zcorr?zt:-1., dydx);
1257 sy[n] = TMath::Sqrt(c->GetSigmaY2());
1258
1259 yc[n] = fReconstructor->UseGAUS() ?
1260 c->GetYloc(y0, sy[n], GetPadWidth()): c->GetY();
1261 zc[n] = c->GetZ();
1262 //optional tilt correction
1263 if(tilt) yc[n] -= (GetTilt()*(zc[n] - zt));
1264
1265 fitterY.AddPoint(&xc[n], yc[n], TMath::Sqrt(sy[n]));
b72f4eaf 1266 fitterZ.AddPoint(&xc[n], qc[n], 1.);
dd8059a8 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
b72f4eaf 1283 fX = -fCov[1]/fCov[2];
b1957d3c 1284
1285 // fit XZ
b72f4eaf 1286 if(IsRowCross()){
e355f67a 1287/* // THE LEADING CLUSTER METHOD
1fd9389f 1288 Float_t xMin = fX0;
b72f4eaf 1289 Int_t ic=n=kNclusters-1; jc = &fClusters[ic];
1fd9389f 1290 AliTRDcluster *c0 =0x0, **kc = &fClusters[kNtb-1];
1291 for(; ic>kNtb; ic--, --jc, --kc){
1292 if((c0 = (*kc)) && c0->IsInChamber() && (xMin>c0->GetX())) xMin = c0->GetX();
1293 if(!(c = (*jc))) continue;
1294 if(!c->IsInChamber()) continue;
1295 zc[kNclusters-1] = c->GetZ();
1296 fX = fX0 - c->GetX();
1297 }
1298 fZfit[0] = .5*(zc[0]+zc[kNclusters-1]); fZfit[1] = 0.;
1299 // Error parameterization
1300 fS2Z = fdX*fZref[1];
e355f67a 1301 fS2Z *= fS2Z; fS2Z *= 0.2887; // 1/sqrt(12)*/
1302
1fd9389f 1303 // THE FIT X-Q PLANE METHOD
e355f67a 1304 Int_t ic=n=kNclusters-1; jc = &fClusters[ic];
b72f4eaf 1305 for(; ic>kNtb; ic--, --jc){
1306 if(!(c = (*jc))) continue;
1307 if(!c->IsInChamber()) continue;
1308 qc[n] = TMath::Abs(c->GetQ());
1309 xc[n] = fX0 - c->GetX();
1310 zc[n] = c->GetZ();
1311 fitterZ.AddPoint(&xc[n], -qc[n], 1.);
1312 n--;
1313 }
1314 // fit XZ
1315 fitterZ.Eval();
1316 if(fitterZ.GetParameter(1)!=0.){
1317 fX = -fitterZ.GetParameter(0)/fitterZ.GetParameter(1);
1318 fX=(fX<0.)?0.:fX;
1319 Float_t dl = .5*AliTRDgeometry::CamHght()+AliTRDgeometry::CdrHght();
1320 fX=(fX> dl)?dl:fX;
07bbc13c 1321 fX-=.055; // TODO to be understood
b72f4eaf 1322 }
1323
1324 fZfit[0] = .5*(zc[0]+zc[kNclusters-1]); fZfit[1] = 0.;
c850c351 1325 // temporary external error parameterization
1326 fS2Z = 0.05+0.4*TMath::Abs(fZref[1]); fS2Z *= fS2Z;
1327 // TODO correct formula
1328 //fS2Z = sigma_x*TMath::Abs(fZref[1]);
b1957d3c 1329 } else {
1330 fZfit[0] = zc[0]; fZfit[1] = 0.;
dd8059a8 1331 fS2Z = GetPadLength()*GetPadLength()/12.;
29b87567 1332 }
b72f4eaf 1333 fS2Y = fCov[0] +2.*fX*fCov[1] + fX*fX*fCov[2];
29b87567 1334 return kTRUE;
e4f2f73d 1335}
1336
e4f2f73d 1337
f29f13a6 1338/*
e3cf3d02 1339//_____________________________________________________________________________
1340void AliTRDseedV1::FitMI()
1341{
1342//
1343// Fit the seed.
1344// Marian Ivanov's version
1345//
1346// linear fit on the y direction with respect to the reference direction.
1347// The residuals for each x (x = xc - x0) are deduced from:
1348// dy = y - yt (1)
1349// the tilting correction is written :
1350// y = yc + h*(zc-zt) (2)
1351// yt = y0+dy/dx*x (3)
1352// zt = z0+dz/dx*x (4)
1353// from (1),(2),(3) and (4)
1354// dy = yc - y0 - (dy/dx + h*dz/dx)*x + h*(zc-z0)
1355// the last term introduces the correction on y direction due to tilting pads. There are 2 ways to account for this:
1356// 1. use tilting correction for calculating the y
1357// 2. neglect tilting correction here and account for it in the error parametrization of the tracklet.
1358 const Float_t kRatio = 0.8;
1359 const Int_t kClmin = 5;
1360 const Float_t kmaxtan = 2;
1361
1362 if (TMath::Abs(fYref[1]) > kmaxtan){
1363 //printf("Exit: Abs(fYref[1]) = %3.3f, kmaxtan = %3.3f\n", TMath::Abs(fYref[1]), kmaxtan);
1364 return; // Track inclined too much
1365 }
1366
1367 Float_t sigmaexp = 0.05 + TMath::Abs(fYref[1] * 0.25); // Expected r.m.s in y direction
dd8059a8 1368 Float_t ycrosscor = GetPadLength() * GetTilt() * 0.5; // Y correction for crossing
e3cf3d02 1369 Int_t fNChange = 0;
1370
1371 Double_t sumw;
1372 Double_t sumwx;
1373 Double_t sumwx2;
1374 Double_t sumwy;
1375 Double_t sumwxy;
1376 Double_t sumwz;
1377 Double_t sumwxz;
1378
1379 // Buffering: Leave it constant fot Performance issues
1380 Int_t zints[kNtb]; // Histograming of the z coordinate
1381 // Get 1 and second max probable coodinates in z
1382 Int_t zouts[2*kNtb];
1383 Float_t allowedz[kNtb]; // Allowed z for given time bin
1384 Float_t yres[kNtb]; // Residuals from reference
dd8059a8 1385 //Float_t anglecor = GetTilt() * fZref[1]; // Correction to the angle
e3cf3d02 1386
1387 Float_t pos[3*kNtb]; memset(pos, 0, 3*kNtb*sizeof(Float_t));
1388 Float_t *fX = &pos[0], *fY = &pos[kNtb], *fZ = &pos[2*kNtb];
1389
1390 Int_t fN = 0; AliTRDcluster *c = 0x0;
1391 fN2 = 0;
1392 for (Int_t i = 0; i < AliTRDtrackerV1::GetNTimeBins(); i++) {
1393 yres[i] = 10000.0;
1394 if (!(c = fClusters[i])) continue;
1395 if(!c->IsInChamber()) continue;
1396 // Residual y
dd8059a8 1397 //yres[i] = fY[i] - fYref[0] - (fYref[1] + anglecor) * fX[i] + GetTilt()*(fZ[i] - fZref[0]);
e3cf3d02 1398 fX[i] = fX0 - c->GetX();
1399 fY[i] = c->GetY();
1400 fZ[i] = c->GetZ();
dd8059a8 1401 yres[i] = fY[i] - GetTilt()*(fZ[i] - (fZref[0] - fX[i]*fZref[1]));
e3cf3d02 1402 zints[fN] = Int_t(fZ[i]);
1403 fN++;
1404 }
1405
1406 if (fN < kClmin){
1407 //printf("Exit fN < kClmin: fN = %d\n", fN);
1408 return;
1409 }
1410 Int_t nz = AliTRDtrackerV1::Freq(fN, zints, zouts, kFALSE);
1411 Float_t fZProb = zouts[0];
1412 if (nz <= 1) zouts[3] = 0;
1413 if (zouts[1] + zouts[3] < kClmin) {
1414 //printf("Exit zouts[1] = %d, zouts[3] = %d\n",zouts[1],zouts[3]);
1415 return;
1416 }
1417
1418 // Z distance bigger than pad - length
1419 if (TMath::Abs(zouts[0]-zouts[2]) > 12.0) zouts[3] = 0;
1420
1421 Int_t breaktime = -1;
1422 Bool_t mbefore = kFALSE;
1423 Int_t cumul[kNtb][2];
1424 Int_t counts[2] = { 0, 0 };
1425
1426 if (zouts[3] >= 3) {
1427
1428 //
1429 // Find the break time allowing one chage on pad-rows
1430 // with maximal number of accepted clusters
1431 //
1432 fNChange = 1;
1433 for (Int_t i = 0; i < AliTRDtrackerV1::GetNTimeBins(); i++) {
1434 cumul[i][0] = counts[0];
1435 cumul[i][1] = counts[1];
1436 if (TMath::Abs(fZ[i]-zouts[0]) < 2) counts[0]++;
1437 if (TMath::Abs(fZ[i]-zouts[2]) < 2) counts[1]++;
1438 }
1439 Int_t maxcount = 0;
1440 for (Int_t i = 0; i < AliTRDtrackerV1::GetNTimeBins(); i++) {
1441 Int_t after = cumul[AliTRDtrackerV1::GetNTimeBins()][0] - cumul[i][0];
1442 Int_t before = cumul[i][1];
1443 if (after + before > maxcount) {
1444 maxcount = after + before;
1445 breaktime = i;
1446 mbefore = kFALSE;
1447 }
1448 after = cumul[AliTRDtrackerV1::GetNTimeBins()-1][1] - cumul[i][1];
1449 before = cumul[i][0];
1450 if (after + before > maxcount) {
1451 maxcount = after + before;
1452 breaktime = i;
1453 mbefore = kTRUE;
1454 }
1455 }
1456 breaktime -= 1;
1457 }
1458
1459 for (Int_t i = 0; i < AliTRDtrackerV1::GetNTimeBins()+1; i++) {
1460 if (i > breaktime) allowedz[i] = mbefore ? zouts[2] : zouts[0];
1461 if (i <= breaktime) allowedz[i] = (!mbefore) ? zouts[2] : zouts[0];
1462 }
1463
1464 if (((allowedz[0] > allowedz[AliTRDtrackerV1::GetNTimeBins()]) && (fZref[1] < 0)) ||
1465 ((allowedz[0] < allowedz[AliTRDtrackerV1::GetNTimeBins()]) && (fZref[1] > 0))) {
1466 //
1467 // Tracklet z-direction not in correspondance with track z direction
1468 //
1469 fNChange = 0;
1470 for (Int_t i = 0; i < AliTRDtrackerV1::GetNTimeBins()+1; i++) {
1471 allowedz[i] = zouts[0]; // Only longest taken
1472 }
1473 }
1474
1475 if (fNChange > 0) {
1476 //
1477 // Cross pad -row tracklet - take the step change into account
1478 //
1479 for (Int_t i = 0; i < AliTRDtrackerV1::GetNTimeBins()+1; i++) {
1480 if (!fClusters[i]) continue;
1481 if(!fClusters[i]->IsInChamber()) continue;
1482 if (TMath::Abs(fZ[i] - allowedz[i]) > 2) continue;
1483 // Residual y
dd8059a8 1484 //yres[i] = fY[i] - fYref[0] - (fYref[1] + anglecor) * fX[i] + GetTilt()*(fZ[i] - fZref[0]);
1485 yres[i] = fY[i] - GetTilt()*(fZ[i] - (fZref[0] - fX[i]*fZref[1]));
f29f13a6 1486// if (TMath::Abs(fZ[i] - fZProb) > 2) {
dd8059a8 1487// if (fZ[i] > fZProb) yres[i] += GetTilt() * GetPadLength();
1488// if (fZ[i] < fZProb) yres[i] -= GetTilt() * GetPadLength();
f29f13a6 1489 }
e3cf3d02 1490 }
1491 }
1492
1493 Double_t yres2[kNtb];
1494 Double_t mean;
1495 Double_t sigma;
1496 for (Int_t i = 0; i < AliTRDtrackerV1::GetNTimeBins()+1; i++) {
1497 if (!fClusters[i]) continue;
1498 if(!fClusters[i]->IsInChamber()) continue;
1499 if (TMath::Abs(fZ[i] - allowedz[i]) > 2) continue;
1500 yres2[fN2] = yres[i];
1501 fN2++;
1502 }
1503 if (fN2 < kClmin) {
1504 //printf("Exit fN2 < kClmin: fN2 = %d\n", fN2);
1505 fN2 = 0;
1506 return;
1507 }
1508 AliMathBase::EvaluateUni(fN2,yres2,mean,sigma, Int_t(fN2*kRatio-2.));
1509 if (sigma < sigmaexp * 0.8) {
1510 sigma = sigmaexp;
1511 }
1512 //Float_t fSigmaY = sigma;
1513
1514 // Reset sums
1515 sumw = 0;
1516 sumwx = 0;
1517 sumwx2 = 0;
1518 sumwy = 0;
1519 sumwxy = 0;
1520 sumwz = 0;
1521 sumwxz = 0;
1522
1523 fN2 = 0;
1524 Float_t fMeanz = 0;
1525 Float_t fMPads = 0;
1526 fUsable = 0;
1527 for (Int_t i = 0; i < AliTRDtrackerV1::GetNTimeBins()+1; i++) {
1528 if (!fClusters[i]) continue;
1529 if (!fClusters[i]->IsInChamber()) continue;
1530 if (TMath::Abs(fZ[i] - allowedz[i]) > 2){fClusters[i] = 0x0; continue;}
1531 if (TMath::Abs(yres[i] - mean) > 4.0 * sigma){fClusters[i] = 0x0; continue;}
1532 SETBIT(fUsable,i);
1533 fN2++;
1534 fMPads += fClusters[i]->GetNPads();
1535 Float_t weight = 1.0;
1536 if (fClusters[i]->GetNPads() > 4) weight = 0.5;
1537 if (fClusters[i]->GetNPads() > 5) weight = 0.2;
1538
1539
1540 Double_t x = fX[i];
1541 //printf("x = %7.3f dy = %7.3f fit %7.3f\n", x, yres[i], fY[i]-yres[i]);
1542
1543 sumw += weight;
1544 sumwx += x * weight;
1545 sumwx2 += x*x * weight;
1546 sumwy += weight * yres[i];
1547 sumwxy += weight * (yres[i]) * x;
1548 sumwz += weight * fZ[i];
1549 sumwxz += weight * fZ[i] * x;
1550
1551 }
1552
1553 if (fN2 < kClmin){
1554 //printf("Exit fN2 < kClmin(2): fN2 = %d\n",fN2);
1555 fN2 = 0;
1556 return;
1557 }
1558 fMeanz = sumwz / sumw;
1559 Float_t correction = 0;
1560 if (fNChange > 0) {
1561 // Tracklet on boundary
1562 if (fMeanz < fZProb) correction = ycrosscor;
1563 if (fMeanz > fZProb) correction = -ycrosscor;
1564 }
1565
1566 Double_t det = sumw * sumwx2 - sumwx * sumwx;
1567 fYfit[0] = (sumwx2 * sumwy - sumwx * sumwxy) / det;
1568 fYfit[1] = (sumw * sumwxy - sumwx * sumwy) / det;
1569
1570 fS2Y = 0;
1571 for (Int_t i = 0; i < AliTRDtrackerV1::GetNTimeBins()+1; i++) {
1572 if (!TESTBIT(fUsable,i)) continue;
1573 Float_t delta = yres[i] - fYfit[0] - fYfit[1] * fX[i];
1574 fS2Y += delta*delta;
1575 }
1576 fS2Y = TMath::Sqrt(fS2Y / Float_t(fN2-2));
1577 // TEMPORARY UNTIL covariance properly calculated
1578 fS2Y = TMath::Max(fS2Y, Float_t(.1));
1579
1580 fZfit[0] = (sumwx2 * sumwz - sumwx * sumwxz) / det;
1581 fZfit[1] = (sumw * sumwxz - sumwx * sumwz) / det;
1582// fYfitR[0] += fYref[0] + correction;
1583// fYfitR[1] += fYref[1];
1584// fYfit[0] = fYfitR[0];
1585 fYfit[1] = -fYfit[1];
1586
1587 UpdateUsed();
f29f13a6 1588}*/
e3cf3d02 1589
e4f2f73d 1590//___________________________________________________________________
203967fc 1591void AliTRDseedV1::Print(Option_t *o) const
e4f2f73d 1592{
1593 //
1594 // Printing the seedstatus
1595 //
1596
b72f4eaf 1597 AliInfo(Form("Det[%3d] X0[%7.2f] Pad{L[%5.2f] W[%5.2f] Tilt[%+6.2f]}", fDet, fX0, GetPadLength(), GetPadWidth(), GetTilt()));
dd8059a8 1598 AliInfo(Form("N[%2d] Nused[%2d] Nshared[%2d] [%d]", GetN(), GetNUsed(), GetNShared(), fN));
b72f4eaf 1599 AliInfo(Form("FLAGS : RC[%c] Kink[%c] SA[%c]", IsRowCross()?'y':'n', IsKink()?'y':'n', IsStandAlone()?'y':'n'));
dd8059a8 1600
1601 Double_t cov[3], x=GetX();
1602 GetCovAt(x, cov);
1603 AliInfo(" | x[cm] | y[cm] | z[cm] | dydx | dzdx |");
1604 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 1605 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 1606
1607
1608 if(strcmp(o, "a")!=0) return;
1609
4dc4dc2e 1610 AliTRDcluster* const* jc = &fClusters[0];
8d2bec9e 1611 for(int ic=0; ic<kNclusters; ic++, jc++) {
4dc4dc2e 1612 if(!(*jc)) continue;
203967fc 1613 (*jc)->Print(o);
4dc4dc2e 1614 }
e4f2f73d 1615}
47d5d320 1616
203967fc 1617
1618//___________________________________________________________________
1619Bool_t AliTRDseedV1::IsEqual(const TObject *o) const
1620{
1621 // Checks if current instance of the class has the same essential members
1622 // as the given one
1623
1624 if(!o) return kFALSE;
1625 const AliTRDseedV1 *inTracklet = dynamic_cast<const AliTRDseedV1*>(o);
1626 if(!inTracklet) return kFALSE;
1627
1628 for (Int_t i = 0; i < 2; i++){
e3cf3d02 1629 if ( fYref[i] != inTracklet->fYref[i] ) return kFALSE;
1630 if ( fZref[i] != inTracklet->fZref[i] ) return kFALSE;
203967fc 1631 }
1632
e3cf3d02 1633 if ( fS2Y != inTracklet->fS2Y ) return kFALSE;
dd8059a8 1634 if ( GetTilt() != inTracklet->GetTilt() ) return kFALSE;
1635 if ( GetPadLength() != inTracklet->GetPadLength() ) return kFALSE;
203967fc 1636
8d2bec9e 1637 for (Int_t i = 0; i < kNclusters; i++){
e3cf3d02 1638// if ( fX[i] != inTracklet->GetX(i) ) return kFALSE;
1639// if ( fY[i] != inTracklet->GetY(i) ) return kFALSE;
1640// if ( fZ[i] != inTracklet->GetZ(i) ) return kFALSE;
1641 if ( fIndexes[i] != inTracklet->fIndexes[i] ) return kFALSE;
203967fc 1642 }
f29f13a6 1643// if ( fUsable != inTracklet->fUsable ) return kFALSE;
203967fc 1644
1645 for (Int_t i=0; i < 2; i++){
e3cf3d02 1646 if ( fYfit[i] != inTracklet->fYfit[i] ) return kFALSE;
1647 if ( fZfit[i] != inTracklet->fZfit[i] ) return kFALSE;
1648 if ( fLabels[i] != inTracklet->fLabels[i] ) return kFALSE;
203967fc 1649 }
1650
e3cf3d02 1651/* if ( fMeanz != inTracklet->GetMeanz() ) return kFALSE;
1652 if ( fZProb != inTracklet->GetZProb() ) return kFALSE;*/
3e778975 1653 if ( fN != inTracklet->fN ) return kFALSE;
1654 //if ( fNUsed != inTracklet->fNUsed ) return kFALSE;
e3cf3d02 1655 //if ( fFreq != inTracklet->GetFreq() ) return kFALSE;
1656 //if ( fNChange != inTracklet->GetNChange() ) return kFALSE;
203967fc 1657
e3cf3d02 1658 if ( fC != inTracklet->fC ) return kFALSE;
1659 //if ( fCC != inTracklet->GetCC() ) return kFALSE;
1660 if ( fChi2 != inTracklet->fChi2 ) return kFALSE;
203967fc 1661 // if ( fChi2Z != inTracklet->GetChi2Z() ) return kFALSE;
1662
e3cf3d02 1663 if ( fDet != inTracklet->fDet ) return kFALSE;
b25a5e9e 1664 if ( fPt != inTracklet->fPt ) return kFALSE;
e3cf3d02 1665 if ( fdX != inTracklet->fdX ) return kFALSE;
203967fc 1666
8d2bec9e 1667 for (Int_t iCluster = 0; iCluster < kNclusters; iCluster++){
203967fc 1668 AliTRDcluster *curCluster = fClusters[iCluster];
e3cf3d02 1669 AliTRDcluster *inCluster = inTracklet->fClusters[iCluster];
203967fc 1670 if (curCluster && inCluster){
1671 if (! curCluster->IsEqual(inCluster) ) {
1672 curCluster->Print();
1673 inCluster->Print();
1674 return kFALSE;
1675 }
1676 } else {
1677 // if one cluster exists, and corresponding
1678 // in other tracklet doesn't - return kFALSE
1679 if(curCluster || inCluster) return kFALSE;
1680 }
1681 }
1682 return kTRUE;
1683}
5d401b45 1684