]> git.uio.no Git - u/mrichter/AliRoot.git/blame - TRD/AliTRDseedV1.cxx
Remove class AliPtMothFromPtDaugh, which introduced unwanted dependency on libSTEER
[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"
eb38ed55 39#include <TTreeStream.h>
e4f2f73d 40
41#include "AliLog.h"
42#include "AliMathBase.h"
d937ad7a 43#include "AliCDBManager.h"
44#include "AliTracker.h"
e4f2f73d 45
03cef9b2 46#include "AliTRDpadPlane.h"
e4f2f73d 47#include "AliTRDcluster.h"
f3d3af1b 48#include "AliTRDseedV1.h"
49#include "AliTRDtrackV1.h"
e4f2f73d 50#include "AliTRDcalibDB.h"
eb38ed55 51#include "AliTRDchamberTimeBin.h"
52#include "AliTRDtrackingChamber.h"
53#include "AliTRDtrackerV1.h"
e4f2f73d 54#include "AliTRDrecoParam.h"
a076fc2f 55#include "AliTRDCommonParam.h"
d937ad7a 56
0906e73e 57#include "Cal/AliTRDCalPID.h"
d937ad7a 58#include "Cal/AliTRDCalROC.h"
59#include "Cal/AliTRDCalDet.h"
e4f2f73d 60
e4f2f73d 61ClassImp(AliTRDseedV1)
62
63//____________________________________________________________________
ae4e8b84 64AliTRDseedV1::AliTRDseedV1(Int_t det)
3e778975 65 :AliTRDtrackletBase()
4d6aee34 66 ,fkReconstructor(NULL)
67 ,fClusterIter(NULL)
e3cf3d02 68 ,fExB(0.)
69 ,fVD(0.)
70 ,fT0(0.)
71 ,fS2PRF(0.)
72 ,fDiffL(0.)
73 ,fDiffT(0.)
ae4e8b84 74 ,fClusterIdx(0)
7c3eecb8 75 ,fErrorMsg(0)
3e778975 76 ,fN(0)
ae4e8b84 77 ,fDet(det)
b25a5e9e 78 ,fPt(0.)
bcb6fb78 79 ,fdX(0.)
e3cf3d02 80 ,fX0(0.)
81 ,fX(0.)
82 ,fY(0.)
83 ,fZ(0.)
84 ,fS2Y(0.)
85 ,fS2Z(0.)
86 ,fC(0.)
87 ,fChi2(0.)
e4f2f73d 88{
89 //
90 // Constructor
91 //
f301a656 92 memset(fIndexes,0xFF,kNclusters*sizeof(fIndexes[0]));
8d2bec9e 93 memset(fClusters, 0, kNclusters*sizeof(AliTRDcluster*));
dd8059a8 94 memset(fPad, 0, 3*sizeof(Float_t));
e3cf3d02 95 fYref[0] = 0.; fYref[1] = 0.;
96 fZref[0] = 0.; fZref[1] = 0.;
97 fYfit[0] = 0.; fYfit[1] = 0.;
98 fZfit[0] = 0.; fZfit[1] = 0.;
8d2bec9e 99 memset(fdEdx, 0, kNslices*sizeof(Float_t));
29b87567 100 for(int ispec=0; ispec<AliPID::kSPECIES; ispec++) fProb[ispec] = -1.;
e3cf3d02 101 fLabels[0]=-1; fLabels[1]=-1; // most freq MC labels
102 fLabels[2]=0; // number of different labels for tracklet
16cca13f 103 memset(fRefCov, 0, 7*sizeof(Double_t));
d937ad7a 104 // covariance matrix [diagonal]
105 // default sy = 200um and sz = 2.3 cm
106 fCov[0] = 4.e-4; fCov[1] = 0.; fCov[2] = 5.3;
f29f13a6 107 SetStandAlone(kFALSE);
e4f2f73d 108}
109
110//____________________________________________________________________
0906e73e 111AliTRDseedV1::AliTRDseedV1(const AliTRDseedV1 &ref)
3e778975 112 :AliTRDtrackletBase((AliTRDtrackletBase&)ref)
4d6aee34 113 ,fkReconstructor(NULL)
114 ,fClusterIter(NULL)
e3cf3d02 115 ,fExB(0.)
116 ,fVD(0.)
117 ,fT0(0.)
118 ,fS2PRF(0.)
119 ,fDiffL(0.)
120 ,fDiffT(0.)
ae4e8b84 121 ,fClusterIdx(0)
7c3eecb8 122 ,fErrorMsg(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];
4d6aee34 176 fClusters[itb] = NULL;
29b87567 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
4d6aee34 191 target.fkReconstructor = fkReconstructor;
192 target.fClusterIter = NULL;
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;
7c3eecb8 200 target.fErrorMsg = fErrorMsg;
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//_____________________________________________________________________________
980d5a2a 256void AliTRDseedV1::Reset(Option_t *opt)
e3cf3d02 257{
980d5a2a 258//
259// Reset seed. If option opt="c" is given only cluster arrays are cleared.
260//
261 for(Int_t ic=kNclusters; ic--;) fIndexes[ic] = -1;
262 memset(fClusters, 0, kNclusters*sizeof(AliTRDcluster*));
560e5c05 263 fN=0; SetBit(kRowCross, kFALSE);
980d5a2a 264 if(strcmp(opt, "c")==0) return;
265
e3cf3d02 266 fExB=0.;fVD=0.;fT0=0.;fS2PRF=0.;
267 fDiffL=0.;fDiffT=0.;
3e778975 268 fClusterIdx=0;
7c3eecb8 269 fErrorMsg = 0;
dd8059a8 270 fDet=-1;
b25a5e9e 271 fPt=0.;
e3cf3d02 272 fdX=0.;fX0=0.; fX=0.; fY=0.; fZ=0.;
273 fS2Y=0.; fS2Z=0.;
274 fC=0.; fChi2 = 0.;
275
dd8059a8 276 memset(fPad, 0, 3*sizeof(Float_t));
e3cf3d02 277 fYref[0] = 0.; fYref[1] = 0.;
278 fZref[0] = 0.; fZref[1] = 0.;
279 fYfit[0] = 0.; fYfit[1] = 0.;
280 fZfit[0] = 0.; fZfit[1] = 0.;
8d2bec9e 281 memset(fdEdx, 0, kNslices*sizeof(Float_t));
e3cf3d02 282 for(int ispec=0; ispec<AliPID::kSPECIES; ispec++) fProb[ispec] = -1.;
283 fLabels[0]=-1; fLabels[1]=-1; // most freq MC labels
284 fLabels[2]=0; // number of different labels for tracklet
16cca13f 285 memset(fRefCov, 0, 7*sizeof(Double_t));
e3cf3d02 286 // covariance matrix [diagonal]
287 // default sy = 200um and sz = 2.3 cm
288 fCov[0] = 4.e-4; fCov[1] = 0.; fCov[2] = 5.3;
289}
290
b1957d3c 291//____________________________________________________________________
16cca13f 292void AliTRDseedV1::Update(const AliTRDtrackV1 *trk)
b1957d3c 293{
294 // update tracklet reference position from the TRD track
b1957d3c 295
e3cf3d02 296 Double_t fSnp = trk->GetSnp();
297 Double_t fTgl = trk->GetTgl();
b25a5e9e 298 fPt = trk->Pt();
bfd20868 299 Double_t norm =1./TMath::Sqrt((1.-fSnp)*(1.+fSnp));
1fd9389f 300 fYref[1] = fSnp*norm;
301 fZref[1] = fTgl*norm;
b1957d3c 302 SetCovRef(trk->GetCovariance());
303
304 Double_t dx = trk->GetX() - fX0;
305 fYref[0] = trk->GetY() - dx*fYref[1];
306 fZref[0] = trk->GetZ() - dx*fZref[1];
307}
308
e3cf3d02 309//_____________________________________________________________________________
310void AliTRDseedV1::UpdateUsed()
311{
312 //
f29f13a6 313 // Calculate number of used clusers in the tracklet
e3cf3d02 314 //
315
3e778975 316 Int_t nused = 0, nshared = 0;
8d2bec9e 317 for (Int_t i = kNclusters; i--; ) {
e3cf3d02 318 if (!fClusters[i]) continue;
3e778975 319 if(fClusters[i]->IsUsed()){
320 nused++;
321 } else if(fClusters[i]->IsShared()){
322 if(IsStandAlone()) nused++;
323 else nshared++;
324 }
e3cf3d02 325 }
3e778975 326 SetNUsed(nused);
327 SetNShared(nshared);
e3cf3d02 328}
329
330//_____________________________________________________________________________
331void AliTRDseedV1::UseClusters()
332{
333 //
334 // Use clusters
335 //
f29f13a6 336 // In stand alone mode:
337 // Clusters which are marked as used or shared from another track are
338 // removed from the tracklet
339 //
340 // In barrel mode:
341 // - Clusters which are used by another track become shared
342 // - Clusters which are attached to a kink track become shared
343 //
e3cf3d02 344 AliTRDcluster **c = &fClusters[0];
8d2bec9e 345 for (Int_t ic=kNclusters; ic--; c++) {
e3cf3d02 346 if(!(*c)) continue;
f29f13a6 347 if(IsStandAlone()){
348 if((*c)->IsShared() || (*c)->IsUsed()){
b82b4de1 349 if((*c)->IsShared()) SetNShared(GetNShared()-1);
350 else SetNUsed(GetNUsed()-1);
4d6aee34 351 (*c) = NULL;
f29f13a6 352 fIndexes[ic] = -1;
3e778975 353 SetN(GetN()-1);
3e778975 354 continue;
f29f13a6 355 }
3e778975 356 } else {
f29f13a6 357 if((*c)->IsUsed() || IsKink()){
3e778975 358 (*c)->SetShared();
359 continue;
f29f13a6 360 }
361 }
362 (*c)->Use();
e3cf3d02 363 }
364}
365
366
f29f13a6 367
bcb6fb78 368//____________________________________________________________________
369void AliTRDseedV1::CookdEdx(Int_t nslices)
370{
371// Calculates average dE/dx for all slices and store them in the internal array fdEdx.
372//
373// Parameters:
374// nslices : number of slices for which dE/dx should be calculated
375// Output:
376// store results in the internal array fdEdx. This can be accessed with the method
377// AliTRDseedV1::GetdEdx()
378//
379// Detailed description
380// Calculates average dE/dx for all slices. Depending on the PID methode
381// the number of slices can be 3 (LQ) or 8(NN).
3ee48d6e 382// The calculation of dQ/dl are done using the tracklet fit results (see AliTRDseedV1::GetdQdl(Int_t))
bcb6fb78 383//
384// The following effects are included in the calculation:
385// 1. calibration values for t0 and vdrift (using x coordinate to calculate slice)
386// 2. cluster sharing (optional see AliTRDrecoParam::SetClusterSharing())
387// 3. cluster size
388//
389
8d2bec9e 390 memset(fdEdx, 0, kNslices*sizeof(Float_t));
e73abf77 391 const Double_t kDriftLength = (.5 * AliTRDgeometry::AmThick() + AliTRDgeometry::DrThick());
29b87567 392
9ded305e 393 AliTRDcluster *c(NULL);
29b87567 394 for(int ic=0; ic<AliTRDtrackerV1::GetNTimeBins(); ic++){
8e709c82 395 if(!(c = fClusters[ic]) && !(c = fClusters[ic+kNtb])) continue;
e73abf77 396 Float_t dx = TMath::Abs(fX0 - c->GetX());
29b87567 397
398 // Filter clusters for dE/dx calculation
399
400 // 1.consider calibration effects for slice determination
e73abf77 401 Int_t slice;
402 if(dx<kDriftLength){ // TODO should be replaced by c->IsInChamber()
403 slice = Int_t(dx * nslices / kDriftLength);
404 } else slice = c->GetX() < fX0 ? nslices-1 : 0;
405
406
29b87567 407 // 2. take sharing into account
3e778975 408 Float_t w = /*c->IsShared() ? .5 :*/ 1.;
29b87567 409
410 // 3. take into account large clusters TODO
411 //w *= c->GetNPads() > 3 ? .8 : 1.;
412
413 //CHECK !!!
414 fdEdx[slice] += w * GetdQdl(ic); //fdQdl[ic];
29b87567 415 } // End of loop over clusters
bcb6fb78 416}
417
e3cf3d02 418//_____________________________________________________________________________
419void AliTRDseedV1::CookLabels()
420{
421 //
422 // Cook 2 labels for seed
423 //
424
425 Int_t labels[200];
426 Int_t out[200];
427 Int_t nlab = 0;
8d2bec9e 428 for (Int_t i = 0; i < kNclusters; i++) {
e3cf3d02 429 if (!fClusters[i]) continue;
430 for (Int_t ilab = 0; ilab < 3; ilab++) {
431 if (fClusters[i]->GetLabel(ilab) >= 0) {
432 labels[nlab] = fClusters[i]->GetLabel(ilab);
433 nlab++;
434 }
435 }
436 }
437
fac58f00 438 fLabels[2] = AliMathBase::Freq(nlab,labels,out,kTRUE);
e3cf3d02 439 fLabels[0] = out[0];
440 if ((fLabels[2] > 1) && (out[3] > 1)) fLabels[1] = out[2];
441}
442
443
bcb6fb78 444//____________________________________________________________________
0b433f72 445Float_t AliTRDseedV1::GetdQdl(Int_t ic, Float_t *dl) const
bcb6fb78 446{
3ee48d6e 447// Using the linear approximation of the track inside one TRD chamber (TRD tracklet)
448// the charge per unit length can be written as:
449// BEGIN_LATEX
500851ab 450// #frac{dq}{dl} = #frac{q_{c}}{dx * #sqrt{1 + #(){#frac{dy}{dx}}^{2}_{fit} + #(){#frac{dz}{dx}}^{2}_{ref}}}
3ee48d6e 451// END_LATEX
452// where qc is the total charge collected in the current time bin and dx is the length
0b433f72 453// of the time bin.
454// The following correction are applied :
455// - charge : pad row cross corrections
456// [diffusion and TRF assymetry] TODO
457// - dx : anisochronity, track inclination - see Fit and AliTRDcluster::GetXloc()
458// and AliTRDcluster::GetYloc() for the effects taken into account
3ee48d6e 459//
0fa1a8ee 460//Begin_Html
461//<img src="TRD/trackletDQDT.gif">
462//End_Html
463// In the picture the energy loss measured on the tracklet as a function of drift time [left] and respectively
464// drift length [right] for different particle species is displayed.
3ee48d6e 465// Author : Alex Bercuci <A.Bercuci@gsi.de>
466//
467 Float_t dq = 0.;
5d401b45 468 // check whether both clusters are inside the chamber
469 Bool_t hasClusterInChamber = kFALSE;
470 if(fClusters[ic] && fClusters[ic]->IsInChamber()){
471 hasClusterInChamber = kTRUE;
1742f24c 472 dq += TMath::Abs(fClusters[ic]->GetQ());
5d401b45 473 }else if(fClusters[ic+kNtb] && fClusters[ic+kNtb]->IsInChamber()){
474 hasClusterInChamber = kTRUE;
475 dq += TMath::Abs(fClusters[ic+kNtb]->GetQ());
1742f24c 476 }
5d401b45 477 if(!hasClusterInChamber) return 0.;
0b433f72 478 if(dq<1.e-3) return 0.;
3ee48d6e 479
a2abcbc5 480 Double_t dx = fdX;
481 if(ic-1>=0 && ic+1<kNtb){
482 Float_t x2(0.), x1(0.);
5d401b45 483 // try to estimate upper radial position (find the cluster which is inside the chamber)
484 if(fClusters[ic-1] && fClusters[ic-1]->IsInChamber()) x2 = fClusters[ic-1]->GetX();
485 else if(fClusters[ic-1+kNtb] && fClusters[ic-1+kNtb]->IsInChamber()) x2 = fClusters[ic-1+kNtb]->GetX();
486 else if(fClusters[ic] && fClusters[ic]->IsInChamber()) x2 = fClusters[ic]->GetX()+fdX;
a2abcbc5 487 else x2 = fClusters[ic+kNtb]->GetX()+fdX;
5d401b45 488 // try to estimate lower radial position (find the cluster which is inside the chamber)
489 if(fClusters[ic+1] && fClusters[ic+1]->IsInChamber()) x1 = fClusters[ic+1]->GetX();
490 else if(fClusters[ic+1+kNtb] && fClusters[ic+1+kNtb]->IsInChamber()) x1 = fClusters[ic+1+kNtb]->GetX();
491 else if(fClusters[ic] && fClusters[ic]->IsInChamber()) x1 = fClusters[ic]->GetX()-fdX;
a2abcbc5 492 else x1 = fClusters[ic+kNtb]->GetX()-fdX;
493
494 dx = .5*(x2 - x1);
495 }
0b433f72 496 dx *= TMath::Sqrt(1. + fYfit[1]*fYfit[1] + fZref[1]*fZref[1]);
0b433f72 497 if(dl) (*dl) = dx;
283604d2 498 if(dx>1.e-9) return dq/dx;
499 else return 0.;
bcb6fb78 500}
501
0b433f72 502//____________________________________________________________
503Float_t AliTRDseedV1::GetMomentum(Float_t *err) const
504{
505// Returns momentum of the track after update with the current tracklet as:
506// BEGIN_LATEX
507// p=#frac{1}{1/p_{t}} #sqrt{1+tgl^{2}}
508// END_LATEX
509// and optionally the momentum error (if err is not null).
510// The estimated variance of the momentum is given by:
511// BEGIN_LATEX
512// #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})
513// END_LATEX
514// which can be simplified to
515// BEGIN_LATEX
516// #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}
517// END_LATEX
518//
519
520 Double_t p = fPt*TMath::Sqrt(1.+fZref[1]*fZref[1]);
521 Double_t p2 = p*p;
522 Double_t tgl2 = fZref[1]*fZref[1];
523 Double_t pt2 = fPt*fPt;
524 if(err){
525 Double_t s2 =
526 p2*tgl2*pt2*pt2*fRefCov[4]
527 -2.*p2*fZref[1]*fPt*pt2*fRefCov[5]
528 +p2*pt2*fRefCov[6];
529 (*err) = TMath::Sqrt(s2);
530 }
531 return p;
532}
533
b453ef55 534//____________________________________________________________________
535Float_t AliTRDseedV1::GetOccupancyTB() const
536{
537// Returns procentage of TB occupied by clusters
538
539 Int_t n(0);
540 AliTRDcluster *c(NULL);
541 for(int ic=0; ic<AliTRDtrackerV1::GetNTimeBins(); ic++){
542 if(!(c = fClusters[ic]) && !(c = fClusters[ic+kNtb])) continue;
543 n++;
544 }
545
546 return Float_t(n)/AliTRDtrackerV1::GetNTimeBins();
547}
0b433f72 548
0906e73e 549//____________________________________________________________________
3e778975 550Float_t* AliTRDseedV1::GetProbability(Bool_t force)
0906e73e 551{
3e778975 552 if(!force) return &fProb[0];
4d6aee34 553 if(!CookPID()) return NULL;
3e778975 554 return &fProb[0];
555}
556
557//____________________________________________________________
558Bool_t AliTRDseedV1::CookPID()
559{
0906e73e 560// Fill probability array for tracklet from the DB.
561//
562// Parameters
563//
564// Output
4d6aee34 565// returns pointer to the probability array and NULL if missing DB access
0906e73e 566//
2a3191bb 567// Retrieve PID probabilities for e+-, mu+-, K+-, pi+- and p+- from the DB according to tracklet information:
568// - estimated momentum at tracklet reference point
569// - dE/dx measurements
570// - tracklet length
571// - TRD layer
572// According to the steering settings specified in the reconstruction one of the following methods are used
573// - Neural Network [default] - option "nn"
574// - 2D Likelihood - option "!nn"
0906e73e 575
0906e73e 576 AliTRDcalibDB *calibration = AliTRDcalibDB::Instance();
577 if (!calibration) {
578 AliError("No access to calibration data");
3e778975 579 return kFALSE;
0906e73e 580 }
581
4d6aee34 582 if (!fkReconstructor) {
3a039a31 583 AliError("Reconstructor not set.");
3e778975 584 return kFALSE;
4ba1d6ae 585 }
586
0906e73e 587 // Retrieve the CDB container class with the parametric detector response
4d6aee34 588 const AliTRDCalPID *pd = calibration->GetPIDObject(fkReconstructor->GetPIDMethod());
0906e73e 589 if (!pd) {
590 AliError("No access to AliTRDCalPID object");
3e778975 591 return kFALSE;
0906e73e 592 }
10f75631 593
29b87567 594 // calculate tracklet length TO DO
560e5c05 595 Float_t length = (AliTRDgeometry::AmThick() + AliTRDgeometry::DrThick())/ TMath::Sqrt((1.0 - GetSnp()*GetSnp()) / (1.0 + GetTgl()*GetTgl()));
0906e73e 596
597 //calculate dE/dx
9ded305e 598 CookdEdx(AliTRDCalPID::kNSlicesNN);
599 AliDebug(4, Form("p=%6.4f[GeV/c] dEdx{%7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f} l=%4.2f[cm]", GetMomentum(), fdEdx[0], fdEdx[1], fdEdx[2], fdEdx[3], fdEdx[4], fdEdx[5], fdEdx[6], fdEdx[7], length));
0217fcd0 600
0906e73e 601 // Sets the a priori probabilities
11d80e40 602 Bool_t kPIDNN(fkReconstructor->GetPIDMethod()==AliTRDpidUtil::kNN);
f83cd814 603 for(int ispec=0; ispec<AliPID::kSPECIES; ispec++)
11d80e40 604 fProb[ispec] = pd->GetProbability(ispec, GetMomentum(), &fdEdx[0], length, kPIDNN?GetPlane():fkReconstructor->GetRecoParam()->GetPIDLQslices());
f301a656 605
3e778975 606 return kTRUE;
0906e73e 607}
608
e4f2f73d 609//____________________________________________________________________
610Float_t AliTRDseedV1::GetQuality(Bool_t kZcorr) const
611{
612 //
613 // Returns a quality measurement of the current seed
614 //
615
dd8059a8 616 Float_t zcorr = kZcorr ? GetTilt() * (fZfit[0] - fZref[0]) : 0.;
29b87567 617 return
3e778975 618 .5 * TMath::Abs(18.0 - GetN())
29b87567 619 + 10.* TMath::Abs(fYfit[1] - fYref[1])
620 + 5. * TMath::Abs(fYfit[0] - fYref[0] + zcorr)
dd8059a8 621 + 2. * TMath::Abs(fZfit[0] - fZref[0]) / GetPadLength();
e4f2f73d 622}
623
0906e73e 624//____________________________________________________________________
d937ad7a 625void AliTRDseedV1::GetCovAt(Double_t x, Double_t *cov) const
0906e73e 626{
d937ad7a 627// Computes covariance in the y-z plane at radial point x (in tracking coordinates)
628// and returns the results in the preallocated array cov[3] as :
629// cov[0] = Var(y)
630// cov[1] = Cov(yz)
631// cov[2] = Var(z)
632//
633// Details
634//
635// For the linear transformation
636// BEGIN_LATEX
637// Y = T_{x} X^{T}
638// END_LATEX
639// The error propagation has the general form
640// BEGIN_LATEX
641// C_{Y} = T_{x} C_{X} T_{x}^{T}
642// END_LATEX
643// We apply this formula 2 times. First to calculate the covariance of the tracklet
644// at point x we consider:
645// BEGIN_LATEX
646// T_{x} = (1 x); X=(y0 dy/dx); C_{X}=#(){#splitline{Var(y0) Cov(y0, dy/dx)}{Cov(y0, dy/dx) Var(dy/dx)}}
647// END_LATEX
648// and secondly to take into account the tilt angle
649// BEGIN_LATEX
650// T_{#alpha} = #(){#splitline{cos(#alpha) __ sin(#alpha)}{-sin(#alpha) __ cos(#alpha)}}; X=(y z); C_{X}=#(){#splitline{Var(y) 0}{0 Var(z)}}
651// END_LATEX
652//
653// using simple trigonometrics one can write for this last case
654// BEGIN_LATEX
655// 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})}}
656// END_LATEX
657// which can be aproximated for small alphas (2 deg) with
658// BEGIN_LATEX
659// 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}}}
660// END_LATEX
661//
662// before applying the tilt rotation we also apply systematic uncertainties to the tracklet
663// position which can be tunned from outside via the AliTRDrecoParam::SetSysCovMatrix(). They might
664// account for extra misalignment/miscalibration uncertainties.
665//
666// Author :
667// Alex Bercuci <A.Bercuci@gsi.de>
668// Date : Jan 8th 2009
669//
b1957d3c 670
671
d937ad7a 672 Double_t xr = fX0-x;
673 Double_t sy2 = fCov[0] +2.*xr*fCov[1] + xr*xr*fCov[2];
b72f4eaf 674 Double_t sz2 = fS2Z;
675 //GetPadLength()*GetPadLength()/12.;
0906e73e 676
d937ad7a 677 // insert systematic uncertainties
4d6aee34 678 if(fkReconstructor){
bb2db46c 679 Double_t sys[15]; memset(sys, 0, 15*sizeof(Double_t));
4d6aee34 680 fkReconstructor->GetRecoParam()->GetSysCovMatrix(sys);
bb2db46c 681 sy2 += sys[0];
682 sz2 += sys[1];
683 }
d937ad7a 684 // rotate covariance matrix
dd8059a8 685 Double_t t2 = GetTilt()*GetTilt();
d937ad7a 686 Double_t correction = 1./(1. + t2);
687 cov[0] = (sy2+t2*sz2)*correction;
dd8059a8 688 cov[1] = GetTilt()*(sz2 - sy2)*correction;
d937ad7a 689 cov[2] = (t2*sy2+sz2)*correction;
b72f4eaf 690
691 //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 692}
eb38ed55 693
bb2db46c 694//____________________________________________________________
4d6aee34 695Double_t AliTRDseedV1::GetCovSqrt(const Double_t * const c, Double_t *d)
bb2db46c 696{
697// Helper function to calculate the square root of the covariance matrix.
698// The input matrix is stored in the vector c and the result in the vector d.
41b7c7b6 699// Both arrays have to be initialized by the user with at least 3 elements. Return negative in case of failure.
bb2db46c 700//
ec3f0161 701// For calculating the square root of the symmetric matrix c
702// the following relation is used:
bb2db46c 703// BEGIN_LATEX
ec3f0161 704// C^{1/2} = VD^{1/2}V^{-1}
bb2db46c 705// END_LATEX
41b7c7b6 706// with V being the matrix with the n eigenvectors as columns.
ec3f0161 707// In case C is symmetric the followings are true:
708// - matrix D is diagonal with the diagonal given by the eigenvalues of C
41b7c7b6 709// - V = V^{-1}
bb2db46c 710//
711// Author A.Bercuci <A.Bercuci@gsi.de>
712// Date Mar 19 2009
713
4d6aee34 714 Double_t l[2], // eigenvalues
715 v[3]; // eigenvectors
bb2db46c 716 // the secular equation and its solution :
717 // (c[0]-L)(c[2]-L)-c[1]^2 = 0
718 // L^2 - L*Tr(c)+DET(c) = 0
719 // L12 = [Tr(c) +- sqrt(Tr(c)^2-4*DET(c))]/2
4d6aee34 720 Double_t tr = c[0]+c[2], // trace
721 det = c[0]*c[2]-c[1]*c[1]; // determinant
722 if(TMath::Abs(det)<1.e-20) return -1.;
723 Double_t dd = TMath::Sqrt(tr*tr - 4*det);
724 l[0] = .5*(tr + dd);
725 l[1] = .5*(tr - dd);
726 if(l[0]<0. || l[1]<0.) return -1.;
41b7c7b6 727
728 // the sym V matrix
729 // | v00 v10|
730 // | v10 v11|
4d6aee34 731 Double_t tmp = (l[0]-c[0])/c[1];
732 v[0] = TMath::Sqrt(1./(tmp*tmp+1));
733 v[1] = tmp*v[0];
734 v[2] = v[1]*c[1]/(l[1]-c[2]);
41b7c7b6 735 // the VD^{1/2}V is:
4d6aee34 736 l[0] = TMath::Sqrt(l[0]); l[1] = TMath::Sqrt(l[1]);
737 d[0] = v[0]*v[0]*l[0]+v[1]*v[1]*l[1];
738 d[1] = v[0]*v[1]*l[0]+v[1]*v[2]*l[1];
739 d[2] = v[1]*v[1]*l[0]+v[2]*v[2]*l[1];
bb2db46c 740
741 return 1.;
742}
743
744//____________________________________________________________
4d6aee34 745Double_t AliTRDseedV1::GetCovInv(const Double_t * const c, Double_t *d)
bb2db46c 746{
747// Helper function to calculate the inverse of the covariance matrix.
748// The input matrix is stored in the vector c and the result in the vector d.
749// Both arrays have to be initialized by the user with at least 3 elements
750// The return value is the determinant or 0 in case of singularity.
751//
752// Author A.Bercuci <A.Bercuci@gsi.de>
753// Date Mar 19 2009
754
4d6aee34 755 Double_t det = c[0]*c[2] - c[1]*c[1];
756 if(TMath::Abs(det)<1.e-20) return 0.;
757 Double_t invDet = 1./det;
758 d[0] = c[2]*invDet;
759 d[1] =-c[1]*invDet;
760 d[2] = c[0]*invDet;
761 return det;
bb2db46c 762}
0906e73e 763
b72f4eaf 764//____________________________________________________________________
765UShort_t AliTRDseedV1::GetVolumeId() const
766{
fbe11be7 767 for(Int_t ic(0);ic<kNclusters; ic++){
768 if(fClusters[ic]) return fClusters[ic]->GetVolumeId();
769 }
770 return 0;
b72f4eaf 771}
772
773
d937ad7a 774//____________________________________________________________________
e3cf3d02 775void AliTRDseedV1::Calibrate()
d937ad7a 776{
e3cf3d02 777// Retrieve calibration and position parameters from OCDB.
778// The following information are used
d937ad7a 779// - detector index
e3cf3d02 780// - column and row position of first attached cluster. If no clusters are attached
781// to the tracklet a random central chamber position (c=70, r=7) will be used.
782//
783// The following information is cached in the tracklet
784// t0 (trigger delay)
785// drift velocity
786// PRF width
787// omega*tau = tg(a_L)
788// diffusion coefficients (longitudinal and transversal)
d937ad7a 789//
790// Author :
791// Alex Bercuci <A.Bercuci@gsi.de>
792// Date : Jan 8th 2009
793//
eb38ed55 794
d937ad7a 795 AliCDBManager *cdb = AliCDBManager::Instance();
796 if(cdb->GetRun() < 0){
797 AliError("OCDB manager not properly initialized");
798 return;
799 }
0906e73e 800
e3cf3d02 801 AliTRDcalibDB *calib = AliTRDcalibDB::Instance();
802 AliTRDCalROC *vdROC = calib->GetVdriftROC(fDet),
803 *t0ROC = calib->GetT0ROC(fDet);;
804 const AliTRDCalDet *vdDet = calib->GetVdriftDet();
805 const AliTRDCalDet *t0Det = calib->GetT0Det();
d937ad7a 806
807 Int_t col = 70, row = 7;
808 AliTRDcluster **c = &fClusters[0];
3e778975 809 if(GetN()){
d937ad7a 810 Int_t ic = 0;
8d2bec9e 811 while (ic<kNclusters && !(*c)){ic++; c++;}
d937ad7a 812 if(*c){
813 col = (*c)->GetPadCol();
814 row = (*c)->GetPadRow();
815 }
816 }
3a039a31 817
e17f4785 818 fT0 = (t0Det->GetValue(fDet) + t0ROC->GetValue(col,row)) / AliTRDCommonParam::Instance()->GetSamplingFrequency();
e3cf3d02 819 fVD = vdDet->GetValue(fDet) * vdROC->GetValue(col, row);
820 fS2PRF = calib->GetPRFWidth(fDet, col, row); fS2PRF *= fS2PRF;
821 fExB = AliTRDCommonParam::Instance()->GetOmegaTau(fVD);
822 AliTRDCommonParam::Instance()->GetDiffCoeff(fDiffL,
823 fDiffT, fVD);
903326c1 824 AliDebug(4, Form("Calibration params for Det[%3d] Col[%3d] Row[%2d]\n t0[%f] vd[%f] s2PRF[%f] ExB[%f] Dl[%f] Dt[%f]", fDet, col, row, fT0, fVD, fS2PRF, fExB, fDiffL, fDiffT));
825
826
e3cf3d02 827 SetBit(kCalib, kTRUE);
0906e73e 828}
829
0906e73e 830//____________________________________________________________________
29b87567 831void AliTRDseedV1::SetOwner()
0906e73e 832{
29b87567 833 //AliInfo(Form("own [%s] fOwner[%s]", own?"YES":"NO", fOwner?"YES":"NO"));
834
835 if(TestBit(kOwner)) return;
8d2bec9e 836 for(int ic=0; ic<kNclusters; ic++){
29b87567 837 if(!fClusters[ic]) continue;
838 fClusters[ic] = new AliTRDcluster(*fClusters[ic]);
839 }
840 SetBit(kOwner);
0906e73e 841}
842
eb2b4f91 843//____________________________________________________________
844void AliTRDseedV1::SetPadPlane(AliTRDpadPlane *p)
845{
846// Shortcut method to initialize pad geometry.
847 if(!p) return;
848 SetTilt(TMath::Tan(TMath::DegToRad()*p->GetTiltingAngle()));
849 SetPadLength(p->GetLengthIPad());
850 SetPadWidth(p->GetWidthIPad());
851}
852
853
e4f2f73d 854//____________________________________________________________________
4d6aee34 855Bool_t AliTRDseedV1::AttachClusters(AliTRDtrackingChamber *const chamber, Bool_t tilt)
e4f2f73d 856{
1fd9389f 857//
858// Projective algorithm to attach clusters to seeding tracklets. The following steps are performed :
859// 1. Collapse x coordinate for the full detector plane
860// 2. truncated mean on y (r-phi) direction
861// 3. purge clusters
862// 4. truncated mean on z direction
863// 5. purge clusters
864//
865// Parameters
866// - chamber : pointer to tracking chamber container used to search the tracklet
867// - tilt : switch for tilt correction during road building [default true]
868// Output
869// - true : if tracklet found successfully. Failure can happend because of the following:
870// -
871// Detailed description
872//
873// We start up by defining the track direction in the xy plane and roads. The roads are calculated based
8a7ff53c 874// on tracking information (variance in the r-phi direction) and estimated variance of the standard
875// clusters (see AliTRDcluster::SetSigmaY2()) corrected for tilt (see GetCovAt()). From this the road is
876// BEGIN_LATEX
500851ab 877// 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 878// r_{z} = 1.5*L_{pad}
879// END_LATEX
1fd9389f 880//
4b755889 881// Author : Alexandru Bercuci <A.Bercuci@gsi.de>
882// Debug : level >3
1fd9389f 883
fc0882f3 884 const AliTRDrecoParam* const recoParam = fkReconstructor->GetRecoParam(); //the dynamic cast in GetRecoParam is slow, so caching the pointer to it
885
886 if(!recoParam){
560e5c05 887 AliError("Tracklets can not be used without a valid RecoParam.");
29b87567 888 return kFALSE;
889 }
b1957d3c 890 // Initialize reco params for this tracklet
891 // 1. first time bin in the drift region
a2abcbc5 892 Int_t t0 = 14;
fc0882f3 893 Int_t kClmin = Int_t(recoParam->GetFindableClusters()*AliTRDtrackerV1::GetNTimeBins());
29b87567 894
fc0882f3 895 Double_t sysCov[5]; recoParam->GetSysCovMatrix(sysCov);
8a7ff53c 896 Double_t s2yTrk= fRefCov[0],
897 s2yCl = 0.,
898 s2zCl = GetPadLength()*GetPadLength()/12.,
899 syRef = TMath::Sqrt(s2yTrk),
900 t2 = GetTilt()*GetTilt();
29b87567 901 //define roads
fc0882f3 902 Double_t kroady = 1., //recoParam->GetRoad1y();
903 kroadz = GetPadLength() * recoParam->GetRoadzMultiplicator() + 1.;
8a7ff53c 904 // define probing cluster (the perfect cluster) and default calibration
905 Short_t sig[] = {0, 0, 10, 30, 10, 0,0};
906 AliTRDcluster cp(fDet, 6, 75, 0, sig, 0);
560e5c05 907 if(fkReconstructor->IsHLT()) cp.SetRPhiMethod(AliTRDcluster::kCOG);
908 if(!IsCalibrated()) Calibrate();
8a7ff53c 909
ee8fb199 910 AliDebug(4, "");
911 AliDebug(4, Form("syKalman[%f] rY[%f] rZ[%f]", syRef, kroady, kroadz));
29b87567 912
913 // working variables
b1957d3c 914 const Int_t kNrows = 16;
4b755889 915 const Int_t kNcls = 3*kNclusters; // buffer size
916 AliTRDcluster *clst[kNrows][kNcls];
3044dfe5 917 Bool_t blst[kNrows][kNcls];
4b755889 918 Double_t cond[4], dx, dy, yt, zt, yres[kNrows][kNcls];
919 Int_t idxs[kNrows][kNcls], ncl[kNrows], ncls = 0;
b1957d3c 920 memset(ncl, 0, kNrows*sizeof(Int_t));
4b755889 921 memset(yres, 0, kNrows*kNcls*sizeof(Double_t));
3044dfe5 922 memset(blst, 0, kNrows*kNcls*sizeof(Bool_t)); //this is 8 times faster to memset than "memset(clst, 0, kNrows*kNcls*sizeof(AliTRDcluster*))"
b1957d3c 923
29b87567 924 // Do cluster projection
4d6aee34 925 AliTRDcluster *c = NULL;
926 AliTRDchamberTimeBin *layer = NULL;
b1957d3c 927 Bool_t kBUFFER = kFALSE;
4b755889 928 for (Int_t it = 0; it < kNtb; it++) {
b1957d3c 929 if(!(layer = chamber->GetTB(it))) continue;
29b87567 930 if(!Int_t(*layer)) continue;
8a7ff53c 931 // get track projection at layers position
b1957d3c 932 dx = fX0 - layer->GetX();
933 yt = fYref[0] - fYref[1] * dx;
934 zt = fZref[0] - fZref[1] * dx;
8a7ff53c 935 // get standard cluster error corrected for tilt
936 cp.SetLocalTimeBin(it);
937 cp.SetSigmaY2(0.02, fDiffT, fExB, dx, -1./*zt*/, fYref[1]);
d956a643 938 s2yCl = (cp.GetSigmaY2() + sysCov[0] + t2*s2zCl)/(1.+t2);
8a7ff53c 939 // get estimated road
940 kroady = 3.*TMath::Sqrt(12.*(s2yTrk + s2yCl));
941
ee8fb199 942 AliDebug(5, Form(" %2d x[%f] yt[%f] zt[%f]", it, dx, yt, zt));
943
944 AliDebug(5, Form(" syTrk[um]=%6.2f syCl[um]=%6.2f syClTlt[um]=%6.2f Ry[mm]=%f", 1.e4*TMath::Sqrt(s2yTrk), 1.e4*TMath::Sqrt(cp.GetSigmaY2()), 1.e4*TMath::Sqrt(s2yCl), 1.e1*kroady));
b1957d3c 945
8a7ff53c 946 // select clusters
b1957d3c 947 cond[0] = yt; cond[2] = kroady;
948 cond[1] = zt; cond[3] = kroadz;
949 Int_t n=0, idx[6];
950 layer->GetClusters(cond, idx, n, 6);
951 for(Int_t ic = n; ic--;){
952 c = (*layer)[idx[ic]];
953 dy = yt - c->GetY();
dd8059a8 954 dy += tilt ? GetTilt() * (c->GetZ() - zt) : 0.;
b1957d3c 955 // select clusters on a 3 sigmaKalman level
956/* if(tilt && TMath::Abs(dy) > 3.*syRef){
957 printf("too large !!!\n");
958 continue;
959 }*/
960 Int_t r = c->GetPadRow();
ee8fb199 961 AliDebug(5, Form(" -> dy[%f] yc[%f] r[%d]", TMath::Abs(dy), c->GetY(), r));
b1957d3c 962 clst[r][ncl[r]] = c;
3044dfe5 963 blst[r][ncl[r]] = kTRUE;
b1957d3c 964 idxs[r][ncl[r]] = idx[ic];
965 yres[r][ncl[r]] = dy;
966 ncl[r]++; ncls++;
967
4b755889 968 if(ncl[r] >= kNcls) {
560e5c05 969 AliWarning(Form("Cluster candidates row[%d] reached buffer limit[%d]. Some may be lost.", r, kNcls));
b1957d3c 970 kBUFFER = kTRUE;
29b87567 971 break;
972 }
973 }
b1957d3c 974 if(kBUFFER) break;
29b87567 975 }
ee8fb199 976 AliDebug(4, Form("Found %d clusters. Processing ...", ncls));
977 if(ncls<kClmin){
560e5c05 978 AliDebug(1, Form("CLUSTERS FOUND %d LESS THAN THRESHOLD %d.", ncls, kClmin));
7c3eecb8 979 SetErrorMsg(kAttachClFound);
ee8fb199 980 return kFALSE;
981 }
982
b1957d3c 983 // analyze each row individualy
560e5c05 984 Bool_t kRowSelection(kFALSE);
985 Double_t mean[]={1.e3, 1.e3, 1.3}, syDis[]={1.e3, 1.e3, 1.3};
986 Int_t nrow[] = {0, 0, 0}, rowId[] = {-1, -1, -1}, nr = 0, lr=-1;
987 TVectorD vdy[3];
988 for(Int_t ir=0; ir<kNrows; ir++){
b1957d3c 989 if(!(ncl[ir])) continue;
560e5c05 990 if(lr>0 && ir-lr != 1){
991 AliDebug(2, "Rows attached not continuous. Turn on selection.");
992 kRowSelection=kTRUE;
29b87567 993 }
560e5c05 994
ee8fb199 995 AliDebug(5, Form(" r[%d] n[%d]", ir, ncl[ir]));
b1957d3c 996 // Evaluate truncated mean on the y direction
560e5c05 997 if(ncl[ir] < 4) continue;
998 AliMathBase::EvaluateUni(ncl[ir], yres[ir], mean[nr], syDis[nr], Int_t(ncl[ir]*.8));
4b755889 999
b1957d3c 1000 // TODO check mean and sigma agains cluster resolution !!
560e5c05 1001 AliDebug(4, Form(" m_%d[%+5.3f (%5.3fs)] s[%f]", nr, mean[nr], TMath::Abs(mean[nr]/syDis[nr]), syDis[nr]));
1002 // remove outliers based on a 3 sigmaDistr level
b1957d3c 1003 Bool_t kFOUND = kFALSE;
1004 for(Int_t ic = ncl[ir]; ic--;){
560e5c05 1005 if(yres[ir][ic] - mean[nr] > 3. * syDis[nr]){
3044dfe5 1006 blst[ir][ic] = kFALSE; continue;
b1957d3c 1007 }
560e5c05 1008 nrow[nr]++; rowId[nr]=ir; kFOUND = kTRUE;
1009 }
1010 if(kFOUND){
1011 vdy[nr].Use(nrow[nr], yres[ir]);
1012 nr++;
b1957d3c 1013 }
b1957d3c 1014 lr = ir; if(nr>=3) break;
29b87567 1015 }
fc0882f3 1016 if(recoParam->GetStreamLevel(AliTRDrecoParam::kTracker) > 3 && fkReconstructor->IsDebugStreaming()){
560e5c05 1017 TTreeSRedirector &cstreamer = *fkReconstructor->GetDebugStream(AliTRDrecoParam::kTracker);
1018 UChar_t stat(0);
1019 if(IsKink()) SETBIT(stat, 1);
1020 if(IsStandAlone()) SETBIT(stat, 2);
1021 cstreamer << "AttachClusters"
1022 << "stat=" << stat
1023 << "det=" << fDet
1024 << "pt=" << fPt
1025 << "s2y=" << s2yTrk
1026 << "r0=" << rowId[0]
1027 << "dy0=" << &vdy[0]
1028 << "m0=" << mean[0]
1029 << "s0=" << syDis[0]
1030 << "r1=" << rowId[1]
1031 << "dy1=" << &vdy[1]
1032 << "m1=" << mean[1]
1033 << "s1=" << syDis[1]
1034 << "r2=" << rowId[2]
1035 << "dy2=" << &vdy[2]
1036 << "m2=" << mean[2]
1037 << "s2=" << syDis[2]
1038 << "\n";
1039 }
1040
1041
1042 // analyze gap in rows attached
1043 if(kRowSelection){
1044 SetErrorMsg(kAttachRowGap);
1045 Int_t rowRemove(-1);
1046 if(nr==2){ // select based on minimum distance to track projection
1047 if(TMath::Abs(mean[0])<TMath::Abs(mean[1])){
1048 if(nrow[1]>nrow[0]) AliDebug(2, Form("Conflicting mean[%f < %f] but ncl[%d < %d].", TMath::Abs(mean[0]), TMath::Abs(mean[1]), nrow[0], nrow[1]));
1049 }else{
1050 if(nrow[1]<nrow[0]) AliDebug(2, Form("Conflicting mean[%f > %f] but ncl[%d > %d].", TMath::Abs(mean[0]), TMath::Abs(mean[1]), nrow[0], nrow[1]));
1051 Swap(nrow[0],nrow[1]); Swap(rowId[0],rowId[1]);
1052 Swap(mean[0],mean[1]); Swap(syDis[0],syDis[1]);
1053 }
1054 rowRemove=1; nr=1;
1055 } else if(nr==3){ // select based on 2 consecutive rows
1056 if(rowId[1]==rowId[0]+1 && rowId[1]!=rowId[2]-1){
1057 nr=2;rowRemove=2;
1058 } else if(rowId[1]!=rowId[0]+1 && rowId[1]==rowId[2]-1){
1059 Swap(nrow[0],nrow[2]); Swap(rowId[0],rowId[2]);
1060 Swap(mean[0],mean[2]); Swap(syDis[0],syDis[2]);
1061 nr=2; rowRemove=2;
1062 }
29b87567 1063 }
560e5c05 1064 if(rowRemove>0){nrow[rowRemove]=0; rowId[rowRemove]=-1;}
29b87567 1065 }
560e5c05 1066 AliDebug(4, Form(" Ncl[%d[%d] + %d[%d] + %d[%d]]", nrow[0], rowId[0], nrow[1], rowId[1], nrow[2], rowId[2]));
1067
1068 if(nr==3){
1069 SetBit(kRowCross, kTRUE); // mark pad row crossing
7c3eecb8 1070 SetErrorMsg(kAttachRow);
560e5c05 1071 const Float_t am[]={TMath::Abs(mean[0]), TMath::Abs(mean[1]), TMath::Abs(mean[2])};
1072 AliDebug(4, Form("complex row configuration\n"
1073 " r[%d] n[%d] m[%6.3f] s[%6.3f]\n"
1074 " r[%d] n[%d] m[%6.3f] s[%6.3f]\n"
1075 " r[%d] n[%d] m[%6.3f] s[%6.3f]\n"
1076 , rowId[0], nrow[0], am[0], syDis[0]
1077 , rowId[1], nrow[1], am[1], syDis[1]
1078 , rowId[2], nrow[2], am[2], syDis[2]));
1079 Int_t id[]={0,1,2}; TMath::Sort(3, am, id, kFALSE);
1080 // backup
1081 Int_t rnn[3]; memcpy(rnn, nrow, 3*sizeof(Int_t));
1082 Int_t rid[3]; memcpy(rid, rowId, 3*sizeof(Int_t));
1083 Double_t rm[3]; memcpy(rm, mean, 3*sizeof(Double_t));
1084 Double_t rs[3]; memcpy(rs, syDis, 3*sizeof(Double_t));
1085 nrow[0]=rnn[id[0]]; rowId[0]=rid[id[0]]; mean[0]=rm[id[0]]; syDis[0]=rs[id[0]];
1086 nrow[1]=rnn[id[1]]; rowId[1]=rid[id[1]]; mean[1]=rm[id[1]]; syDis[1]=rs[id[1]];
1087 nrow[2]=0; rowId[2]=-1; mean[2] = 1.e3; syDis[2] = 1.e3;
1088 AliDebug(4, Form("solved configuration\n"
1089 " r[%d] n[%d] m[%+6.3f] s[%6.3f]\n"
1090 " r[%d] n[%d] m[%+6.3f] s[%6.3f]\n"
1091 " r[%d] n[%d] m[%+6.3f] s[%6.3f]\n"
1092 , rowId[0], nrow[0], mean[0], syDis[0]
1093 , rowId[1], nrow[1], mean[1], syDis[1]
1094 , rowId[2], nrow[2], mean[2], syDis[2]));
1095 nr=2;
1096 } else if(nr==2) {
1097 SetBit(kRowCross, kTRUE); // mark pad row crossing
1098 if(nrow[1] > nrow[0]){ // swap row order
1099 Swap(nrow[0],nrow[1]); Swap(rowId[0],rowId[1]);
1100 Swap(mean[0],mean[1]); Swap(syDis[0],syDis[1]);
1101 }
ee8fb199 1102 }
560e5c05 1103
b1957d3c 1104 // Select and store clusters
1105 // We should consider here :
1106 // 1. How far is the chamber boundary
1107 // 2. How big is the mean
560e5c05 1108 Int_t n(0); Float_t dyc[kNclusters]; memset(dyc,0,kNclusters*sizeof(Float_t));
b1957d3c 1109 for (Int_t ir = 0; ir < nr; ir++) {
560e5c05 1110 Int_t jr(rowId[ir]);
1111 AliDebug(4, Form(" Attaching Ncl[%d]=%d ...", jr, ncl[jr]));
b1957d3c 1112 for (Int_t ic = 0; ic < ncl[jr]; ic++) {
3044dfe5 1113 if(!blst[jr][ic])continue;
1114 c = clst[jr][ic];
560e5c05 1115 Int_t it(c->GetPadTime());
1116 Int_t idx(it+kNtb*ir);
6ad5e6b2 1117 if(fClusters[idx]){
560e5c05 1118 AliDebug(4, Form("Many cluster candidates on row[%2d] tb[%2d].", jr, it));
1119 // TODO should save also the information on where the multiplicity happened and its size
6ad5e6b2 1120 SetErrorMsg(kAttachMultipleCl);
560e5c05 1121 // TODO should also compare with mean and sigma for this row
1122 if(yres[jr][ic] > dyc[idx]) continue;
6ad5e6b2 1123 }
1124
b1957d3c 1125 // TODO proper indexing of clusters !!
6ad5e6b2 1126 fIndexes[idx] = chamber->GetTB(it)->GetGlobalIndex(idxs[jr][ic]);
1127 fClusters[idx] = c;
560e5c05 1128 dyc[idx] = yres[jr][ic];
3e778975 1129 n++;
b1957d3c 1130 }
560e5c05 1131 }
6ad5e6b2 1132 SetN(n);
b1957d3c 1133
29b87567 1134 // number of minimum numbers of clusters expected for the tracklet
6ad5e6b2 1135 if (GetN() < kClmin){
560e5c05 1136 AliDebug(1, Form("NOT ENOUGH CLUSTERS %d ATTACHED TO THE TRACKLET [min %d] FROM FOUND %d.", GetN(), kClmin, n));
7c3eecb8 1137 SetErrorMsg(kAttachClAttach);
e4f2f73d 1138 return kFALSE;
1139 }
0906e73e 1140
e3cf3d02 1141 // Load calibration parameters for this tracklet
1142 Calibrate();
b1957d3c 1143
1144 // calculate dx for time bins in the drift region (calibration aware)
a2abcbc5 1145 Float_t x[2] = {0.,0.}; Int_t tb[2]={0,0};
1146 for (Int_t it = t0, irp=0; irp<2 && it < AliTRDtrackerV1::GetNTimeBins(); it++) {
b1957d3c 1147 if(!fClusters[it]) continue;
1148 x[irp] = fClusters[it]->GetX();
a2abcbc5 1149 tb[irp] = fClusters[it]->GetLocalTimeBin();
b1957d3c 1150 irp++;
e3cf3d02 1151 }
d86ed84c 1152 Int_t dtb = tb[1] - tb[0];
1153 fdX = dtb ? (x[0] - x[1]) / dtb : 0.15;
29b87567 1154 return kTRUE;
e4f2f73d 1155}
1156
03cef9b2 1157//____________________________________________________________
1158void AliTRDseedV1::Bootstrap(const AliTRDReconstructor *rec)
1159{
1160// Fill in all derived information. It has to be called after recovery from file or HLT.
1161// The primitive data are
1162// - list of clusters
1163// - detector (as the detector will be removed from clusters)
1164// - position of anode wire (fX0) - temporary
1165// - track reference position and direction
1166// - momentum of the track
1167// - time bin length [cm]
1168//
1169// A.Bercuci <A.Bercuci@gsi.de> Oct 30th 2008
1170//
4d6aee34 1171 fkReconstructor = rec;
03cef9b2 1172 AliTRDgeometry g;
1173 AliTRDpadPlane *pp = g.GetPadPlane(fDet);
dd8059a8 1174 fPad[0] = pp->GetLengthIPad();
1175 fPad[1] = pp->GetWidthIPad();
525f399b 1176 fPad[2] = TMath::Tan(TMath::DegToRad()*pp->GetTiltingAngle());
e3cf3d02 1177 //fSnp = fYref[1]/TMath::Sqrt(1+fYref[1]*fYref[1]);
1178 //fTgl = fZref[1];
3e778975 1179 Int_t n = 0, nshare = 0, nused = 0;
03cef9b2 1180 AliTRDcluster **cit = &fClusters[0];
8d2bec9e 1181 for(Int_t ic = kNclusters; ic--; cit++){
03cef9b2 1182 if(!(*cit)) return;
3e778975 1183 n++;
1184 if((*cit)->IsShared()) nshare++;
1185 if((*cit)->IsUsed()) nused++;
03cef9b2 1186 }
3e778975 1187 SetN(n); SetNUsed(nused); SetNShared(nshare);
e3cf3d02 1188 Fit();
03cef9b2 1189 CookLabels();
1190 GetProbability();
1191}
1192
1193
e4f2f73d 1194//____________________________________________________________________
b72f4eaf 1195Bool_t AliTRDseedV1::Fit(Bool_t tilt, Bool_t zcorr)
e4f2f73d 1196{
16cca13f 1197//
1198// Linear fit of the clusters attached to the tracklet
1199//
1200// Parameters :
1201// - tilt : switch for tilt pad correction of cluster y position based on
1202// the z, dzdx info from outside [default false].
1203// - zcorr : switch for using z information to correct for anisochronity
1fd9389f 1204// and a finner error parameterization estimation [default false]
16cca13f 1205// Output :
1206// True if successful
1207//
1208// Detailed description
1209//
1210// Fit in the xy plane
1211//
1fd9389f 1212// The fit is performed to estimate the y position of the tracklet and the track
1213// angle in the bending plane. The clusters are represented in the chamber coordinate
1214// system (with respect to the anode wire - see AliTRDtrackerV1::FollowBackProlongation()
1215// on how this is set). The x and y position of the cluster and also their variances
1216// are known from clusterizer level (see AliTRDcluster::GetXloc(), AliTRDcluster::GetYloc(),
1217// AliTRDcluster::GetSX() and AliTRDcluster::GetSY()).
1218// If gaussian approximation is used to calculate y coordinate of the cluster the position
1219// is recalculated taking into account the track angle. The general formula to calculate the
1220// error of cluster position in the gaussian approximation taking into account diffusion and track
1221// inclination is given for TRD by:
1222// BEGIN_LATEX
1223// #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}
1224// END_LATEX
1225//
1226// Since errors are calculated only in the y directions, radial errors (x direction) are mapped to y
1227// by projection i.e.
1228// BEGIN_LATEX
1229// #sigma_{x|y} = tg(#phi) #sigma_{x}
1230// END_LATEX
1231// and also by the lorentz angle correction
1232//
1233// Fit in the xz plane
1234//
1235// The "fit" is performed to estimate the radial position (x direction) where pad row cross happens.
1236// If no pad row crossing the z position is taken from geometry and radial position is taken from the xy
1237// fit (see below).
1238//
1239// There are two methods to estimate the radial position of the pad row cross:
1240// 1. leading cluster radial position : Here the lower part of the tracklet is considered and the last
1241// cluster registered (at radial x0) on this segment is chosen to mark the pad row crossing. The error
1242// of the z estimate is given by :
1243// BEGIN_LATEX
1244// #sigma_{z} = tg(#theta) #Delta x_{x_{0}}/12
1245// END_LATEX
1246// The systematic errors for this estimation are generated by the following sources:
1247// - no charge sharing between pad rows is considered (sharp cross)
1248// - missing cluster at row cross (noise peak-up, under-threshold signal etc.).
1249//
1250// 2. charge fit over the crossing point : Here the full energy deposit along the tracklet is considered
1251// to estimate the position of the crossing by a fit in the qx plane. The errors in the q directions are
1252// parameterized as s_q = q^2. The systematic errors for this estimation are generated by the following sources:
1253// - no general model for the qx dependence
1254// - physical fluctuations of the charge deposit
1255// - gain calibration dependence
1256//
1257// Estimation of the radial position of the tracklet
16cca13f 1258//
1fd9389f 1259// For pad row cross the radial position is taken from the xz fit (see above). Otherwise it is taken as the
1260// interpolation point of the tracklet i.e. the point where the error in y of the fit is minimum. The error
1261// in the y direction of the tracklet is (see AliTRDseedV1::GetCovAt()):
1262// BEGIN_LATEX
1263// #sigma_{y} = #sigma^{2}_{y_{0}} + 2xcov(y_{0}, dy/dx) + #sigma^{2}_{dy/dx}
1264// END_LATEX
1265// and thus the radial position is:
1266// BEGIN_LATEX
1267// x = - cov(y_{0}, dy/dx)/#sigma^{2}_{dy/dx}
1268// END_LATEX
1269//
1270// Estimation of tracklet position error
1271//
1272// The error in y direction is the error of the linear fit at the radial position of the tracklet while in the z
1273// direction is given by the cluster error or pad row cross error. In case of no pad row cross this is given by:
1274// BEGIN_LATEX
1275// #sigma_{y} = #sigma^{2}_{y_{0}} - 2cov^{2}(y_{0}, dy/dx)/#sigma^{2}_{dy/dx} + #sigma^{2}_{dy/dx}
1276// #sigma_{z} = Pad_{length}/12
1277// END_LATEX
1278// For pad row cross the full error is calculated at the radial position of the crossing (see above) and the error
1279// in z by the width of the crossing region - being a matter of parameterization.
1280// BEGIN_LATEX
1281// #sigma_{z} = tg(#theta) #Delta x_{x_{0}}/12
1282// END_LATEX
1283// In case of no tilt correction (default in the barrel tracking) the tilt is taken into account by the rotation of
1284// the covariance matrix. See AliTRDseedV1::GetCovAt() for details.
1285//
1286// Author
1287// A.Bercuci <A.Bercuci@gsi.de>
e4f2f73d 1288
a723055f 1289 if(!fkReconstructor){
1290 AliError("The tracklet needs the reconstruction setup. Please initialize by SetReconstructor().");
1291 return kFALSE;
1292 }
b72f4eaf 1293 if(!IsCalibrated()) Calibrate();
e3cf3d02 1294
29b87567 1295 const Int_t kClmin = 8;
010d62b0 1296
2f7d6ac8 1297 // get track direction
1298 Double_t y0 = fYref[0];
1299 Double_t dydx = fYref[1];
1300 Double_t z0 = fZref[0];
1301 Double_t dzdx = fZref[1];
1302 Double_t yt, zt;
ae4e8b84 1303
5f1ae1e7 1304 AliTRDtrackerV1::AliTRDLeastSquare fitterY;
1305 AliTRDtrackerV1::AliTRDLeastSquare fitterZ;
f301a656 1306
29b87567 1307 // book cluster information
8d2bec9e 1308 Double_t qc[kNclusters], xc[kNclusters], yc[kNclusters], zc[kNclusters], sy[kNclusters];
e3cf3d02 1309
dd8059a8 1310 Int_t n = 0;
4d6aee34 1311 AliTRDcluster *c=NULL, **jc = &fClusters[0];
fc0882f3 1312 const AliTRDrecoParam* const recoParam = fkReconstructor->GetRecoParam(); //the dynamic cast in GetRecoParam is slow, so caching the pointer to it
9eb2d46c 1313 for (Int_t ic=0; ic<kNtb; ic++, ++jc) {
29b87567 1314 xc[ic] = -1.;
1315 yc[ic] = 999.;
1316 zc[ic] = 999.;
1317 sy[ic] = 0.;
9eb2d46c 1318 if(!(c = (*jc))) continue;
29b87567 1319 if(!c->IsInChamber()) continue;
9462866a 1320
29b87567 1321 Float_t w = 1.;
1322 if(c->GetNPads()>4) w = .5;
1323 if(c->GetNPads()>5) w = .2;
010d62b0 1324
1fd9389f 1325 // cluster charge
dd8059a8 1326 qc[n] = TMath::Abs(c->GetQ());
1fd9389f 1327 // pad row of leading
1328
b72f4eaf 1329 // Radial cluster position
e3cf3d02 1330 //Int_t jc = TMath::Max(fN-3, 0);
1331 //xc[fN] = c->GetXloc(fT0, fVD, &qc[jc], &xc[jc]/*, z0 - c->GetX()*dzdx*/);
b72f4eaf 1332 xc[n] = fX0 - c->GetX();
1333
1fd9389f 1334 // extrapolated track to cluster position
dd8059a8 1335 yt = y0 - xc[n]*dydx;
dd8059a8 1336 zt = z0 - xc[n]*dzdx;
1fd9389f 1337
1338 // Recalculate cluster error based on tracking information
1339 c->SetSigmaY2(fS2PRF, fDiffT, fExB, xc[n], zcorr?zt:-1., dydx);
1340 sy[n] = TMath::Sqrt(c->GetSigmaY2());
1341
fc0882f3 1342 yc[n] = recoParam->UseGAUS() ?
1fd9389f 1343 c->GetYloc(y0, sy[n], GetPadWidth()): c->GetY();
1344 zc[n] = c->GetZ();
1345 //optional tilt correction
1346 if(tilt) yc[n] -= (GetTilt()*(zc[n] - zt));
1347
fbe11be7 1348 AliDebug(5, Form(" tb[%2d] dx[%6.3f] y[%6.2f+-%6.3f]", c->GetLocalTimeBin(), xc[n], yc[n], sy[n]));
903326c1 1349 fitterY.AddPoint(&xc[n], yc[n], sy[n]);
0217fcd0 1350 if(IsRowCross()) fitterZ.AddPoint(&xc[n], qc[n], 1.);
dd8059a8 1351 n++;
29b87567 1352 }
3044dfe5 1353
47d5d320 1354 // to few clusters
dd8059a8 1355 if (n < kClmin) return kFALSE;
2f7d6ac8 1356
d937ad7a 1357 // fit XY
903326c1 1358 if(!fitterY.Eval()){
1359 SetErrorMsg(kFitFailed);
1360 return kFALSE;
1361 }
5f1ae1e7 1362 fYfit[0] = fitterY.GetFunctionParameter(0);
1363 fYfit[1] = -fitterY.GetFunctionParameter(1);
d937ad7a 1364 // store covariance
5f1ae1e7 1365 Double_t p[3];
1366 fitterY.GetCovarianceMatrix(p);
903326c1 1367 fCov[0] = p[1]; // variance of y0
5f1ae1e7 1368 fCov[1] = p[2]; // covariance of y0, dydx
903326c1 1369 fCov[2] = p[0]; // variance of dydx
b1957d3c 1370 // the ref radial position is set at the minimum of
1371 // the y variance of the tracklet
b72f4eaf 1372 fX = -fCov[1]/fCov[2];
903326c1 1373 Float_t xs=fX+.5*AliTRDgeometry::CamHght();
1374 if(xs < 0. || xs > AliTRDgeometry::CamHght()+AliTRDgeometry::CdrHght()){
1375 AliDebug(1, Form("Ref radial position ouside chamber x[%5.2f].", fX));
1376 SetErrorMsg(kFitOutside);
1377 return kFALSE;
1378 }
b1957d3c 1379
0217fcd0 1380 // collect second row clusters
1381 Int_t m(0);
b72f4eaf 1382 if(IsRowCross()){
e355f67a 1383/* // THE LEADING CLUSTER METHOD
1fd9389f 1384 Float_t xMin = fX0;
b72f4eaf 1385 Int_t ic=n=kNclusters-1; jc = &fClusters[ic];
1fd9389f 1386 AliTRDcluster *c0 =0x0, **kc = &fClusters[kNtb-1];
1387 for(; ic>kNtb; ic--, --jc, --kc){
1388 if((c0 = (*kc)) && c0->IsInChamber() && (xMin>c0->GetX())) xMin = c0->GetX();
1389 if(!(c = (*jc))) continue;
1390 if(!c->IsInChamber()) continue;
1391 zc[kNclusters-1] = c->GetZ();
1392 fX = fX0 - c->GetX();
1393 }
1394 fZfit[0] = .5*(zc[0]+zc[kNclusters-1]); fZfit[1] = 0.;
1395 // Error parameterization
1396 fS2Z = fdX*fZref[1];
e355f67a 1397 fS2Z *= fS2Z; fS2Z *= 0.2887; // 1/sqrt(12)*/
1398
1fd9389f 1399 // THE FIT X-Q PLANE METHOD
e355f67a 1400 Int_t ic=n=kNclusters-1; jc = &fClusters[ic];
b72f4eaf 1401 for(; ic>kNtb; ic--, --jc){
1402 if(!(c = (*jc))) continue;
1403 if(!c->IsInChamber()) continue;
1404 qc[n] = TMath::Abs(c->GetQ());
1405 xc[n] = fX0 - c->GetX();
1406 zc[n] = c->GetZ();
1407 fitterZ.AddPoint(&xc[n], -qc[n], 1.);
0217fcd0 1408 n--;m++;
b72f4eaf 1409 }
0217fcd0 1410 }
1411 // fit XZ
1412 if(m && IsRowCross()){
b72f4eaf 1413 fitterZ.Eval();
5f1ae1e7 1414 if(fitterZ.GetFunctionParameter(1)!=0.){
1415 fX = -fitterZ.GetFunctionParameter(0)/fitterZ.GetFunctionParameter(1);
b72f4eaf 1416 fX=(fX<0.)?0.:fX;
1417 Float_t dl = .5*AliTRDgeometry::CamHght()+AliTRDgeometry::CdrHght();
1418 fX=(fX> dl)?dl:fX;
07bbc13c 1419 fX-=.055; // TODO to be understood
b72f4eaf 1420 }
1421
1422 fZfit[0] = .5*(zc[0]+zc[kNclusters-1]); fZfit[1] = 0.;
c850c351 1423 // temporary external error parameterization
1424 fS2Z = 0.05+0.4*TMath::Abs(fZref[1]); fS2Z *= fS2Z;
1425 // TODO correct formula
1426 //fS2Z = sigma_x*TMath::Abs(fZref[1]);
b1957d3c 1427 } else {
0217fcd0 1428 if(IsRowCross() && !m){
1429 AliDebug(1, "Tracklet crossed row but no clusters found in neighbor row.");
1430 }
b1957d3c 1431 fZfit[0] = zc[0]; fZfit[1] = 0.;
dd8059a8 1432 fS2Z = GetPadLength()*GetPadLength()/12.;
29b87567 1433 }
b72f4eaf 1434 fS2Y = fCov[0] +2.*fX*fCov[1] + fX*fX*fCov[2];
29b87567 1435 return kTRUE;
e4f2f73d 1436}
1437
e4f2f73d 1438
f29f13a6 1439/*
e3cf3d02 1440//_____________________________________________________________________________
1441void AliTRDseedV1::FitMI()
1442{
1443//
1444// Fit the seed.
1445// Marian Ivanov's version
1446//
1447// linear fit on the y direction with respect to the reference direction.
1448// The residuals for each x (x = xc - x0) are deduced from:
1449// dy = y - yt (1)
1450// the tilting correction is written :
1451// y = yc + h*(zc-zt) (2)
1452// yt = y0+dy/dx*x (3)
1453// zt = z0+dz/dx*x (4)
1454// from (1),(2),(3) and (4)
1455// dy = yc - y0 - (dy/dx + h*dz/dx)*x + h*(zc-z0)
1456// the last term introduces the correction on y direction due to tilting pads. There are 2 ways to account for this:
1457// 1. use tilting correction for calculating the y
1458// 2. neglect tilting correction here and account for it in the error parametrization of the tracklet.
1459 const Float_t kRatio = 0.8;
1460 const Int_t kClmin = 5;
1461 const Float_t kmaxtan = 2;
1462
1463 if (TMath::Abs(fYref[1]) > kmaxtan){
1464 //printf("Exit: Abs(fYref[1]) = %3.3f, kmaxtan = %3.3f\n", TMath::Abs(fYref[1]), kmaxtan);
1465 return; // Track inclined too much
1466 }
1467
1468 Float_t sigmaexp = 0.05 + TMath::Abs(fYref[1] * 0.25); // Expected r.m.s in y direction
dd8059a8 1469 Float_t ycrosscor = GetPadLength() * GetTilt() * 0.5; // Y correction for crossing
e3cf3d02 1470 Int_t fNChange = 0;
1471
1472 Double_t sumw;
1473 Double_t sumwx;
1474 Double_t sumwx2;
1475 Double_t sumwy;
1476 Double_t sumwxy;
1477 Double_t sumwz;
1478 Double_t sumwxz;
1479
1480 // Buffering: Leave it constant fot Performance issues
1481 Int_t zints[kNtb]; // Histograming of the z coordinate
1482 // Get 1 and second max probable coodinates in z
1483 Int_t zouts[2*kNtb];
1484 Float_t allowedz[kNtb]; // Allowed z for given time bin
1485 Float_t yres[kNtb]; // Residuals from reference
dd8059a8 1486 //Float_t anglecor = GetTilt() * fZref[1]; // Correction to the angle
e3cf3d02 1487
1488 Float_t pos[3*kNtb]; memset(pos, 0, 3*kNtb*sizeof(Float_t));
1489 Float_t *fX = &pos[0], *fY = &pos[kNtb], *fZ = &pos[2*kNtb];
1490
1491 Int_t fN = 0; AliTRDcluster *c = 0x0;
1492 fN2 = 0;
1493 for (Int_t i = 0; i < AliTRDtrackerV1::GetNTimeBins(); i++) {
1494 yres[i] = 10000.0;
1495 if (!(c = fClusters[i])) continue;
1496 if(!c->IsInChamber()) continue;
1497 // Residual y
dd8059a8 1498 //yres[i] = fY[i] - fYref[0] - (fYref[1] + anglecor) * fX[i] + GetTilt()*(fZ[i] - fZref[0]);
e3cf3d02 1499 fX[i] = fX0 - c->GetX();
1500 fY[i] = c->GetY();
1501 fZ[i] = c->GetZ();
dd8059a8 1502 yres[i] = fY[i] - GetTilt()*(fZ[i] - (fZref[0] - fX[i]*fZref[1]));
e3cf3d02 1503 zints[fN] = Int_t(fZ[i]);
1504 fN++;
1505 }
1506
1507 if (fN < kClmin){
1508 //printf("Exit fN < kClmin: fN = %d\n", fN);
1509 return;
1510 }
1511 Int_t nz = AliTRDtrackerV1::Freq(fN, zints, zouts, kFALSE);
1512 Float_t fZProb = zouts[0];
1513 if (nz <= 1) zouts[3] = 0;
1514 if (zouts[1] + zouts[3] < kClmin) {
1515 //printf("Exit zouts[1] = %d, zouts[3] = %d\n",zouts[1],zouts[3]);
1516 return;
1517 }
1518
1519 // Z distance bigger than pad - length
1520 if (TMath::Abs(zouts[0]-zouts[2]) > 12.0) zouts[3] = 0;
1521
1522 Int_t breaktime = -1;
1523 Bool_t mbefore = kFALSE;
1524 Int_t cumul[kNtb][2];
1525 Int_t counts[2] = { 0, 0 };
1526
1527 if (zouts[3] >= 3) {
1528
1529 //
1530 // Find the break time allowing one chage on pad-rows
1531 // with maximal number of accepted clusters
1532 //
1533 fNChange = 1;
1534 for (Int_t i = 0; i < AliTRDtrackerV1::GetNTimeBins(); i++) {
1535 cumul[i][0] = counts[0];
1536 cumul[i][1] = counts[1];
1537 if (TMath::Abs(fZ[i]-zouts[0]) < 2) counts[0]++;
1538 if (TMath::Abs(fZ[i]-zouts[2]) < 2) counts[1]++;
1539 }
1540 Int_t maxcount = 0;
1541 for (Int_t i = 0; i < AliTRDtrackerV1::GetNTimeBins(); i++) {
1542 Int_t after = cumul[AliTRDtrackerV1::GetNTimeBins()][0] - cumul[i][0];
1543 Int_t before = cumul[i][1];
1544 if (after + before > maxcount) {
1545 maxcount = after + before;
1546 breaktime = i;
1547 mbefore = kFALSE;
1548 }
1549 after = cumul[AliTRDtrackerV1::GetNTimeBins()-1][1] - cumul[i][1];
1550 before = cumul[i][0];
1551 if (after + before > maxcount) {
1552 maxcount = after + before;
1553 breaktime = i;
1554 mbefore = kTRUE;
1555 }
1556 }
1557 breaktime -= 1;
1558 }
1559
1560 for (Int_t i = 0; i < AliTRDtrackerV1::GetNTimeBins()+1; i++) {
1561 if (i > breaktime) allowedz[i] = mbefore ? zouts[2] : zouts[0];
1562 if (i <= breaktime) allowedz[i] = (!mbefore) ? zouts[2] : zouts[0];
1563 }
1564
1565 if (((allowedz[0] > allowedz[AliTRDtrackerV1::GetNTimeBins()]) && (fZref[1] < 0)) ||
1566 ((allowedz[0] < allowedz[AliTRDtrackerV1::GetNTimeBins()]) && (fZref[1] > 0))) {
1567 //
1568 // Tracklet z-direction not in correspondance with track z direction
1569 //
1570 fNChange = 0;
1571 for (Int_t i = 0; i < AliTRDtrackerV1::GetNTimeBins()+1; i++) {
1572 allowedz[i] = zouts[0]; // Only longest taken
1573 }
1574 }
1575
1576 if (fNChange > 0) {
1577 //
1578 // Cross pad -row tracklet - take the step change into account
1579 //
1580 for (Int_t i = 0; i < AliTRDtrackerV1::GetNTimeBins()+1; i++) {
1581 if (!fClusters[i]) continue;
1582 if(!fClusters[i]->IsInChamber()) continue;
1583 if (TMath::Abs(fZ[i] - allowedz[i]) > 2) continue;
1584 // Residual y
dd8059a8 1585 //yres[i] = fY[i] - fYref[0] - (fYref[1] + anglecor) * fX[i] + GetTilt()*(fZ[i] - fZref[0]);
1586 yres[i] = fY[i] - GetTilt()*(fZ[i] - (fZref[0] - fX[i]*fZref[1]));
f29f13a6 1587// if (TMath::Abs(fZ[i] - fZProb) > 2) {
dd8059a8 1588// if (fZ[i] > fZProb) yres[i] += GetTilt() * GetPadLength();
1589// if (fZ[i] < fZProb) yres[i] -= GetTilt() * GetPadLength();
f29f13a6 1590 }
e3cf3d02 1591 }
1592 }
1593
1594 Double_t yres2[kNtb];
1595 Double_t mean;
1596 Double_t sigma;
1597 for (Int_t i = 0; i < AliTRDtrackerV1::GetNTimeBins()+1; i++) {
1598 if (!fClusters[i]) continue;
1599 if(!fClusters[i]->IsInChamber()) continue;
1600 if (TMath::Abs(fZ[i] - allowedz[i]) > 2) continue;
1601 yres2[fN2] = yres[i];
1602 fN2++;
1603 }
1604 if (fN2 < kClmin) {
1605 //printf("Exit fN2 < kClmin: fN2 = %d\n", fN2);
1606 fN2 = 0;
1607 return;
1608 }
1609 AliMathBase::EvaluateUni(fN2,yres2,mean,sigma, Int_t(fN2*kRatio-2.));
1610 if (sigma < sigmaexp * 0.8) {
1611 sigma = sigmaexp;
1612 }
1613 //Float_t fSigmaY = sigma;
1614
1615 // Reset sums
1616 sumw = 0;
1617 sumwx = 0;
1618 sumwx2 = 0;
1619 sumwy = 0;
1620 sumwxy = 0;
1621 sumwz = 0;
1622 sumwxz = 0;
1623
1624 fN2 = 0;
1625 Float_t fMeanz = 0;
1626 Float_t fMPads = 0;
1627 fUsable = 0;
1628 for (Int_t i = 0; i < AliTRDtrackerV1::GetNTimeBins()+1; i++) {
1629 if (!fClusters[i]) continue;
1630 if (!fClusters[i]->IsInChamber()) continue;
1631 if (TMath::Abs(fZ[i] - allowedz[i]) > 2){fClusters[i] = 0x0; continue;}
1632 if (TMath::Abs(yres[i] - mean) > 4.0 * sigma){fClusters[i] = 0x0; continue;}
1633 SETBIT(fUsable,i);
1634 fN2++;
1635 fMPads += fClusters[i]->GetNPads();
1636 Float_t weight = 1.0;
1637 if (fClusters[i]->GetNPads() > 4) weight = 0.5;
1638 if (fClusters[i]->GetNPads() > 5) weight = 0.2;
1639
1640
1641 Double_t x = fX[i];
1642 //printf("x = %7.3f dy = %7.3f fit %7.3f\n", x, yres[i], fY[i]-yres[i]);
1643
1644 sumw += weight;
1645 sumwx += x * weight;
1646 sumwx2 += x*x * weight;
1647 sumwy += weight * yres[i];
1648 sumwxy += weight * (yres[i]) * x;
1649 sumwz += weight * fZ[i];
1650 sumwxz += weight * fZ[i] * x;
1651
1652 }
1653
1654 if (fN2 < kClmin){
1655 //printf("Exit fN2 < kClmin(2): fN2 = %d\n",fN2);
1656 fN2 = 0;
1657 return;
1658 }
1659 fMeanz = sumwz / sumw;
1660 Float_t correction = 0;
1661 if (fNChange > 0) {
1662 // Tracklet on boundary
1663 if (fMeanz < fZProb) correction = ycrosscor;
1664 if (fMeanz > fZProb) correction = -ycrosscor;
1665 }
1666
1667 Double_t det = sumw * sumwx2 - sumwx * sumwx;
1668 fYfit[0] = (sumwx2 * sumwy - sumwx * sumwxy) / det;
1669 fYfit[1] = (sumw * sumwxy - sumwx * sumwy) / det;
1670
1671 fS2Y = 0;
1672 for (Int_t i = 0; i < AliTRDtrackerV1::GetNTimeBins()+1; i++) {
1673 if (!TESTBIT(fUsable,i)) continue;
1674 Float_t delta = yres[i] - fYfit[0] - fYfit[1] * fX[i];
1675 fS2Y += delta*delta;
1676 }
1677 fS2Y = TMath::Sqrt(fS2Y / Float_t(fN2-2));
1678 // TEMPORARY UNTIL covariance properly calculated
1679 fS2Y = TMath::Max(fS2Y, Float_t(.1));
1680
1681 fZfit[0] = (sumwx2 * sumwz - sumwx * sumwxz) / det;
1682 fZfit[1] = (sumw * sumwxz - sumwx * sumwz) / det;
1683// fYfitR[0] += fYref[0] + correction;
1684// fYfitR[1] += fYref[1];
1685// fYfit[0] = fYfitR[0];
1686 fYfit[1] = -fYfit[1];
1687
1688 UpdateUsed();
f29f13a6 1689}*/
e3cf3d02 1690
e4f2f73d 1691//___________________________________________________________________
203967fc 1692void AliTRDseedV1::Print(Option_t *o) const
e4f2f73d 1693{
1694 //
1695 // Printing the seedstatus
1696 //
1697
b72f4eaf 1698 AliInfo(Form("Det[%3d] X0[%7.2f] Pad{L[%5.2f] W[%5.2f] Tilt[%+6.2f]}", fDet, fX0, GetPadLength(), GetPadWidth(), GetTilt()));
dd8059a8 1699 AliInfo(Form("N[%2d] Nused[%2d] Nshared[%2d] [%d]", GetN(), GetNUsed(), GetNShared(), fN));
b72f4eaf 1700 AliInfo(Form("FLAGS : RC[%c] Kink[%c] SA[%c]", IsRowCross()?'y':'n', IsKink()?'y':'n', IsStandAlone()?'y':'n'));
525f399b 1701 AliInfo(Form("CALIB PARAMS : T0[%5.2f] Vd[%5.2f] s2PRF[%5.2f] ExB[%5.2f] Dl[%5.2f] Dt[%5.2f]", fT0, fVD, fS2PRF, fExB, fDiffL, fDiffT));
dd8059a8 1702
1703 Double_t cov[3], x=GetX();
1704 GetCovAt(x, cov);
1705 AliInfo(" | x[cm] | y[cm] | z[cm] | dydx | dzdx |");
1706 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 1707 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]))
ee8fb199 1708 AliInfo(Form("P / Pt [GeV/c] = %f / %f", GetMomentum(), fPt));
1709 AliInfo(Form("dEdx [a.u.] = %f / %f / %f / %f / %f/ %f / %f / %f", fdEdx[0], fdEdx[1], fdEdx[2], fdEdx[3], fdEdx[4], fdEdx[5], fdEdx[6], fdEdx[7]));
1710 AliInfo(Form("PID = %5.3f / %5.3f / %5.3f / %5.3f / %5.3f", fProb[0], fProb[1], fProb[2], fProb[3], fProb[4]));
203967fc 1711
1712 if(strcmp(o, "a")!=0) return;
1713
4dc4dc2e 1714 AliTRDcluster* const* jc = &fClusters[0];
8d2bec9e 1715 for(int ic=0; ic<kNclusters; ic++, jc++) {
4dc4dc2e 1716 if(!(*jc)) continue;
203967fc 1717 (*jc)->Print(o);
4dc4dc2e 1718 }
e4f2f73d 1719}
47d5d320 1720
203967fc 1721
1722//___________________________________________________________________
1723Bool_t AliTRDseedV1::IsEqual(const TObject *o) const
1724{
1725 // Checks if current instance of the class has the same essential members
1726 // as the given one
1727
1728 if(!o) return kFALSE;
1729 const AliTRDseedV1 *inTracklet = dynamic_cast<const AliTRDseedV1*>(o);
1730 if(!inTracklet) return kFALSE;
1731
1732 for (Int_t i = 0; i < 2; i++){
e3cf3d02 1733 if ( fYref[i] != inTracklet->fYref[i] ) return kFALSE;
1734 if ( fZref[i] != inTracklet->fZref[i] ) return kFALSE;
203967fc 1735 }
1736
e3cf3d02 1737 if ( fS2Y != inTracklet->fS2Y ) return kFALSE;
dd8059a8 1738 if ( GetTilt() != inTracklet->GetTilt() ) return kFALSE;
1739 if ( GetPadLength() != inTracklet->GetPadLength() ) return kFALSE;
203967fc 1740
8d2bec9e 1741 for (Int_t i = 0; i < kNclusters; i++){
e3cf3d02 1742// if ( fX[i] != inTracklet->GetX(i) ) return kFALSE;
1743// if ( fY[i] != inTracklet->GetY(i) ) return kFALSE;
1744// if ( fZ[i] != inTracklet->GetZ(i) ) return kFALSE;
1745 if ( fIndexes[i] != inTracklet->fIndexes[i] ) return kFALSE;
203967fc 1746 }
f29f13a6 1747// if ( fUsable != inTracklet->fUsable ) return kFALSE;
203967fc 1748
1749 for (Int_t i=0; i < 2; i++){
e3cf3d02 1750 if ( fYfit[i] != inTracklet->fYfit[i] ) return kFALSE;
1751 if ( fZfit[i] != inTracklet->fZfit[i] ) return kFALSE;
1752 if ( fLabels[i] != inTracklet->fLabels[i] ) return kFALSE;
203967fc 1753 }
1754
e3cf3d02 1755/* if ( fMeanz != inTracklet->GetMeanz() ) return kFALSE;
1756 if ( fZProb != inTracklet->GetZProb() ) return kFALSE;*/
3e778975 1757 if ( fN != inTracklet->fN ) return kFALSE;
1758 //if ( fNUsed != inTracklet->fNUsed ) return kFALSE;
e3cf3d02 1759 //if ( fFreq != inTracklet->GetFreq() ) return kFALSE;
1760 //if ( fNChange != inTracklet->GetNChange() ) return kFALSE;
203967fc 1761
e3cf3d02 1762 if ( fC != inTracklet->fC ) return kFALSE;
1763 //if ( fCC != inTracklet->GetCC() ) return kFALSE;
1764 if ( fChi2 != inTracklet->fChi2 ) return kFALSE;
203967fc 1765 // if ( fChi2Z != inTracklet->GetChi2Z() ) return kFALSE;
1766
e3cf3d02 1767 if ( fDet != inTracklet->fDet ) return kFALSE;
b25a5e9e 1768 if ( fPt != inTracklet->fPt ) return kFALSE;
e3cf3d02 1769 if ( fdX != inTracklet->fdX ) return kFALSE;
203967fc 1770
8d2bec9e 1771 for (Int_t iCluster = 0; iCluster < kNclusters; iCluster++){
203967fc 1772 AliTRDcluster *curCluster = fClusters[iCluster];
e3cf3d02 1773 AliTRDcluster *inCluster = inTracklet->fClusters[iCluster];
203967fc 1774 if (curCluster && inCluster){
1775 if (! curCluster->IsEqual(inCluster) ) {
1776 curCluster->Print();
1777 inCluster->Print();
1778 return kFALSE;
1779 }
1780 } else {
1781 // if one cluster exists, and corresponding
1782 // in other tracklet doesn't - return kFALSE
1783 if(curCluster || inCluster) return kFALSE;
1784 }
1785 }
1786 return kTRUE;
1787}
5d401b45 1788