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