Added protection in AliHMPIDParam::FindTemp() in case tLow is equal to tHigh
[u/mrichter/AliRoot.git] / ITS / AliITSTPArrayFit.cxx
CommitLineData
6be22b3f 1/**************************************************************************
2 * Copyright(c) 2009-2011, 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 **************************************************************************/
15/* $Id$ */
16///////////////////////////////////////////////////////////////////////////////////////////////
17// //
18// The line is defined by equations (1) //
19// a0*z+a1*x-a0*a1=0 and //
20// b0*z+b1*y-b0*b1=0 //
21// where x,y,z are NOT the lab axes but z is the lab axis along which the track //
22// has the largest lever arm and x,y are the remaining 2 axis in //
23// the order of fgkAxisID[z][0], fgkAxisID[z][1] //
24// The parameters are fParams[kA0,kB0,kA1,kB1] and the axis chosen as the independent //
25// var. is fParAxis (i.e. if fParAxis==kZ, then a0=ax,b0=bx, a1=ay,b1=by) //
26// //
27// //
28// The helix is defined by the equations (2) //
29// X(t) = (dr+R)*cos(phi0) - (R+sum{dRi})*cos(t+phi0) + sum{dRi*cos(phi0+ti)} //
30// Y(t) = (dr+R)*sin(phi0) - (R+sum{dRi})*sin(t+phi0) + sum{dRi*sin(phi0+ti)} //
31// Z(t) = dz - (R+sum{dRi})*t*tg(dip) + sum{dRi*ti}*tg(dip) //
32// where dRi is the change of the radius due to the ELoss at parameter ti //
33// //
34// Author: ruben.shahoyan@cern.ch //
35// //
36///////////////////////////////////////////////////////////////////////////////////////////////
37
38#include "AliITSTPArrayFit.h"
39#include "AliExternalTrackParam.h"
40#include "AliSymMatrix.h"
41#include "AliLog.h"
42#include "AliParamSolver.h"
43#include "AliGeomManager.h"
44#include "AliITSgeomTGeo.h"
45#include "AliTracker.h"
46#include <TRandom.h>
66214d86 47#include <TGeoMatrix.h>
6be22b3f 48
49ClassImp(AliITSTPArrayFit)
50
51const Int_t AliITSTPArrayFit::fgkAxisID[3][3] = {
52 {AliITSTPArrayFit::kY,AliITSTPArrayFit::kZ,AliITSTPArrayFit::kX},
53 {AliITSTPArrayFit::kZ,AliITSTPArrayFit::kX,AliITSTPArrayFit::kY},
54 {AliITSTPArrayFit::kX,AliITSTPArrayFit::kY,AliITSTPArrayFit::kZ} };
55
56const Int_t AliITSTPArrayFit::fgkAxisCID[3][6] = {
57 {AliITSTPArrayFit::kYY,AliITSTPArrayFit::kYZ,AliITSTPArrayFit::kXY,
58 AliITSTPArrayFit::kZZ,AliITSTPArrayFit::kXZ,AliITSTPArrayFit::kXX},
59 //
60 {AliITSTPArrayFit::kZZ,AliITSTPArrayFit::kXZ,AliITSTPArrayFit::kYZ,
61 AliITSTPArrayFit::kXX,AliITSTPArrayFit::kYX,AliITSTPArrayFit::kYY},
62 //
63 {AliITSTPArrayFit::kXX,AliITSTPArrayFit::kXY,AliITSTPArrayFit::kXZ,
64 AliITSTPArrayFit::kYY,AliITSTPArrayFit::kYZ,AliITSTPArrayFit::kZZ}
65};
66//
67
68const Double_t AliITSTPArrayFit::fgkAlmostZero = 1E-55;
69const Double_t AliITSTPArrayFit::fgkCQConv = 0.299792458e-3;// R = PT/Bz/fgkCQConv with GeV,kGauss,cm
70const Double_t AliITSTPArrayFit::fgkZSpanITS[AliITSTPArrayFit::kMaxLrITS] = {
71 36. ,14.1,14.1, 38., 22.2,29.7, 51. ,43.1,48.9};
72
73const Double_t AliITSTPArrayFit::fgkRLayITS[AliITSTPArrayFit::kMaxLrITS] = {
74 2.94, 3.9,7.6, 11.04, 15.0,23.9, 29.44 ,38.0,43.0};
75
76const Int_t AliITSTPArrayFit::fgkPassivLrITS[3] =
77 {AliITSTPArrayFit::kLrBeamPime,AliITSTPArrayFit::kLrShield1,AliITSTPArrayFit::kLrShield2};
78
79const Int_t AliITSTPArrayFit::fgkActiveLrITS[6] =
80 {AliITSTPArrayFit::kLrSPD1,AliITSTPArrayFit::kLrSPD2,
81 AliITSTPArrayFit::kLrSDD1,AliITSTPArrayFit::kLrSDD2,
82 AliITSTPArrayFit::kLrSSD1,AliITSTPArrayFit::kLrSSD2};
83
84Double_t AliITSTPArrayFit::fgRhoLITS[AliITSTPArrayFit::kMaxLrITS] = {
85 1.48e-01, 2.48e-01,2.57e-01, 1.34e-01, 3.34e-01,3.50e-01, 2.22e-01, 2.38e-01,2.25e-01};
86
87//____________________________________________________
88AliITSTPArrayFit::AliITSTPArrayFit() :
89 fPoints(0),fParSol(0),fBz(0),fCharge(0),fPntFirst(-1),
90 fPntLast(-1),fNPBooked(0),fParAxis(-1),fCovI(0),fChi2NDF(0),
1d06ac63 91 fMaxIter(20),fIter(0),fEps(1e-6),fMass(0),fSwitch2Line(kFALSE),fMaxRforHelix(1.e6),
92 fkAxID(0),fkAxCID(0),fCurT(0),
6be22b3f 93 fFirstPosT(0),fNElsPnt(0),fElsId(0),fElsDR(0)
94{
95 // default constructor
96 for (int i=kMaxParam;i--;) fParams[i] = 0;
97 for (int i=kMaxParamSq;i--;) fParamsCov[i] = 0;
98 SetMass();
99}
100
101//____________________________________________________
102AliITSTPArrayFit::AliITSTPArrayFit(Int_t np) :
103 fPoints(0),fParSol(0),fBz(0),fCharge(0),fPntFirst(-1),
104 fPntLast(-1),fNPBooked(np),fParAxis(-1),fCovI(0),fChi2NDF(0),
1d06ac63 105 fMaxIter(20),fIter(0),fEps(1e-6),fMass(0),fSwitch2Line(kFALSE),fMaxRforHelix(2.e3),
106 fkAxID(0),fkAxCID(0),fCurT(0),fFirstPosT(0),fNElsPnt(0),fElsId(0),fElsDR(0)
6be22b3f 107{
108 // constructor with booking of np points
109 for (int i=kMaxParam;i--;) fParams[i] = 0;
110 for (int i=kMaxParamSq;i--;) fParamsCov[i] = 0;
111 InitAux();
112 SetEps();
113 SetMass();
114 SetMaxIterations();
115}
116
117//____________________________________________________
118AliITSTPArrayFit::AliITSTPArrayFit(const AliITSTPArrayFit &src) :
119 TObject(src),fPoints(src.fPoints),fParSol(0),fBz(src.fBz),
120 fCharge(src.fCharge),fPntFirst(src.fPntFirst),fPntLast(src.fPntLast),fNPBooked(src.fNPBooked),
121 fParAxis(src.fParAxis),fCovI(0),fChi2NDF(0),fMaxIter(20),fIter(0),fEps(0),fMass(src.fMass),
1d06ac63 122 fSwitch2Line(src.fSwitch2Line),fMaxRforHelix(src.fMaxRforHelix),fkAxID(0),fkAxCID(0),fCurT(0),
123 fFirstPosT(0),fNElsPnt(0),fElsId(0),fElsDR(0)
6be22b3f 124{
125 // copy constructor
126 InitAux();
127 memcpy(fCovI,src.fCovI,fNPBooked*6*sizeof(Double_t));
128 for (int i=kMaxParam;i--;) fParams[i] = src.fParams[i];
129 for (int i=kMaxParamSq;i--;) fParamsCov[i] = src.fParamsCov[i];
130 memcpy(fCurT,src.fCurT,fNPBooked*sizeof(Double_t));
131 SetEps(src.fEps);
132 SetMaxIterations(src.fMaxIter);
133 //
134}
135
136//____________________________________________________
137AliITSTPArrayFit &AliITSTPArrayFit::operator =(const AliITSTPArrayFit& src)
138{
139 // assignment operator
140 if (this==&src) return *this;
141 ((TObject*)this)->operator=(src);
142 fPoints = src.fPoints;
143 if (!fParSol) fParSol = new AliParamSolver(*src.fParSol);
144 else *fParSol = *src.fParSol;
145 fBz = src.fBz;
146 fCharge = src.fCharge;
147 fNPBooked = src.fNPBooked;
148 fPntFirst = src.fPntFirst;
149 fPntLast = src.fPntLast;
150 InitAux();
151 memcpy(fCovI,src.fCovI,fNPBooked*6*sizeof(Double_t));
152 for (int i=kMaxParam;i--;) fParams[i] = src.fParams[i];
153 for (int i=kMaxParamSq;i--;) fParamsCov[i] = src.fParamsCov[i];
154 SetParAxis(src.fParAxis);
155 fNElsPnt = src.fNElsPnt;
156 fFirstPosT = src.fFirstPosT;
157 memcpy(fCurT ,src.fCurT ,fNPBooked*sizeof(Double_t));
158 memcpy(fElsId ,src.fElsId ,fNPBooked*sizeof(Int_t));
159 memcpy(fElsDR ,src.fElsDR ,fNPBooked*sizeof(Double_t));
160 memcpy(fCurT ,src.fCurT ,fNPBooked*sizeof(Double_t));
161 SetEps(src.fEps);
162 SetMaxIterations(src.fMaxIter);
163 //
164 return *this;
165 //
166}
167
168//____________________________________________________
169AliITSTPArrayFit::~AliITSTPArrayFit()
170{
171 // destructor
172 delete fParSol;
173 delete[] fCovI;
174 delete[] fCurT;
175 delete[] fElsId;
176 delete[] fElsDR;
177}
178
179//____________________________________________________
180void AliITSTPArrayFit::Reset()
181{
182 // reset to process new track
183 if (fParSol) fParSol->Clear();
184 fPoints=0;
185 fNElsPnt = 0;
186 fFirstPosT = 0;
187 // fBz = 0;
188 fCharge = 0;
189 fIter = 0;
190 fPntFirst=fPntLast=-1;
191 SetParAxis(-1);
1d06ac63 192 fSwitch2Line = kFALSE;
6be22b3f 193 ResetBit(kFitDoneBit|kCovInvBit);
194}
195
196//____________________________________________________
197void AliITSTPArrayFit::AttachPoints(const AliTrackPointArray* points, Int_t pfirst,Int_t plast)
198{
199 // create from piece of AliTrackPointArray
200 Reset();
201 fPoints = points;
202 int np = points->GetNPoints();
203 if (fNPBooked<np) {
204 fNPBooked = np;
205 InitAux();
206 }
207 fPntFirst = pfirst<0 ? 0 : pfirst;
208 fPntLast = plast<fPntFirst ? np-1 : plast;
209 //
210 for (int i=kMaxParam;i--;) fParams[i] = 0;
211 for (int i=kMaxParamSq;i--;) fParamsCov[i] = 0;
212 //
213 InvertPointsCovMat();
214 //
215}
216
217//____________________________________________________
218Bool_t AliITSTPArrayFit::SetFirstLast(Int_t pfirst,Int_t plast)
219{
220 // set first and last point to fit
221 const AliTrackPointArray* pnts = fPoints;
222 if (!pnts) {AliError("TrackPointArray is not attached yet"); return kFALSE;}
223 AttachPoints(pnts,pfirst,plast);
224 return kTRUE;
225 //
226}
227
228//____________________________________________________
229Bool_t AliITSTPArrayFit::InvertPointsCovMat()
230{
231 // invert the cov.matrices of the points
232 for (int i=fPntFirst;i<=fPntLast;i++) {
233 //
66214d86 234 float *cov = (float*)fPoints->GetCov() + i*6; // pointer on cov.matrix
6be22b3f 235 //
236 Double_t t0 = cov[kYY]*cov[kZZ] - cov[kYZ]*cov[kYZ];
237 Double_t t1 = cov[kXY]*cov[kZZ] - cov[kXZ]*cov[kYZ];
238 Double_t t2 = cov[kXY]*cov[kYZ] - cov[kXZ]*cov[kYY];
239 Double_t det = cov[kXX]*t0 - cov[kXY]*t1 + cov[kXZ]*t2;
66214d86 240 if (IsZero(det,1e-18)) { // one of errors is 0, fix this
241 double norm[3];
242 TGeoHMatrix hcov;
243 TGeoRotation hrot,hrotI;
244 GetNormal(norm,cov);
245 double phi = TMath::ATan2(norm[1],norm[0]);
246 hrot.SetAngles(-phi*TMath::RadToDeg(),0.,0.);
247 hrotI.SetAngles(phi*TMath::RadToDeg(),0.,0.);
248 //
249 Double_t hcovel[9];
250 hcovel[0] = cov[kXX];
251 hcovel[1] = cov[kXY];
252 hcovel[2] = cov[kXZ];
253 hcovel[3] = cov[kXY];
254 hcovel[4] = cov[kYY];
255 hcovel[5] = cov[kYZ];
256 hcovel[6] = cov[kXZ];
257 hcovel[7] = cov[kYZ];
258 hcovel[8] = cov[kZZ];
259 hcov.SetRotation(hcovel);
260 //
261 Double_t *hcovscl = hcov.GetRotationMatrix();
262 // printf(">> %+e %+e %+e\n %+e %+e %+e\n %+e %+e %+e\n\n",hcovscl[0],hcovscl[1],hcovscl[2],hcovscl[3],hcovscl[4],hcovscl[5],hcovscl[6],hcovscl[7],hcovscl[8]);
263 // printf("Rot by %+.e (%+.e %+.e %+.e)\n",phi, norm[0],norm[1],norm[2]);
264 hcov.Multiply(&hrotI);
265 hcov.MultiplyLeft(&hrot);
266 // printf("|| %+e %+e %+e\n %+e %+e %+e\n %+e %+e %+e\n\n",hcovscl[0],hcovscl[1],hcovscl[2],hcovscl[3],hcovscl[4],hcovscl[5],hcovscl[6],hcovscl[7],hcovscl[8]);
267 if (hcovscl[0]<1e-8) hcovscl[0] = 1e-8;
268 if (hcovscl[4]<1e-8) hcovscl[4] = 1e-8;
269 if (hcovscl[8]<1e-8) hcovscl[8] = 1e-8;
270 // printf("** %+e %+e %+e\n %+e %+e %+e\n %+e %+e %+e\n\n",hcovscl[0],hcovscl[1],hcovscl[2],hcovscl[3],hcovscl[4],hcovscl[5],hcovscl[6],hcovscl[7],hcovscl[8]);
271 hcov.Multiply(&hrot);
272 hcov.MultiplyLeft(&hrotI);
273 // printf("^^ %+e %+e %+e\n %+e %+e %+e\n %+e %+e %+e\n\n",hcovscl[0],hcovscl[1],hcovscl[2],hcovscl[3],hcovscl[4],hcovscl[5],hcovscl[6],hcovscl[7],hcovscl[8]);
274 cov[kXX] = hcovscl[0];
275 cov[kXY] = hcovscl[1];
276 cov[kXZ] = hcovscl[2];
277 cov[kYY] = hcovscl[4];
278 cov[kYZ] = hcovscl[5];
279 cov[kZZ] = hcovscl[8];
280 }
281 t0 = cov[kYY]*cov[kZZ] - cov[kYZ]*cov[kYZ];
282 t1 = cov[kXY]*cov[kZZ] - cov[kXZ]*cov[kYZ];
283 t2 = cov[kXY]*cov[kYZ] - cov[kXZ]*cov[kYY];
284 det = cov[kXX]*t0 - cov[kXY]*t1 + cov[kXZ]*t2;
285 //
abd7ef79 286 AliDebug(2,Form("%+.4e %+.4e %+.4e -> %+.4e",t0,t1,t2,det));
66214d86 287 if (IsZero(det,fgkAlmostZero)) {
6be22b3f 288 AliInfo(Form("Cov.Matrix for point %d is singular",i));
289 return kFALSE;
290 }
291 //
292 Double_t *covI = GetCovI(i);
293 covI[kXX] = t0/det;
294 covI[kXY] = -t1/det;
295 covI[kXZ] = t2/det;
296 covI[kYY] = (cov[kXX]*cov[kZZ] - cov[kXZ]*cov[kXZ])/det;
297 covI[kYZ] = (cov[kXY]*cov[kXZ] - cov[kXX]*cov[kYZ])/det;
298 covI[kZZ] = (cov[kXX]*cov[kYY] - cov[kXY]*cov[kXY])/det;
299 //
300 }
301 SetCovInv();
302 return kTRUE;
303}
304
305//____________________________________________________
306void AliITSTPArrayFit::InitAux()
307{
308 // init auxiliary space
309 if (fCovI) delete[] fCovI;
310 if (fCurT) delete[] fCurT;
311 //
312 fCovI = new Double_t[6*fNPBooked];
313 fCurT = new Double_t[fNPBooked+kMaxLrITS];
314 fElsId = new Int_t[fNPBooked+kMaxLrITS];
315 fElsDR = new Double_t[fNPBooked+kMaxLrITS];
316 memset(fElsDR,0,(fNPBooked+kMaxLrITS)*sizeof(Double_t));
317 memset(fCovI,0,fNPBooked*6*sizeof(Double_t));
318 //
319}
320
321//____________________________________________________
322Bool_t AliITSTPArrayFit::FitLineCrude()
323{
324 // perform linear fit w/o accounting the errors
325 // fit is done in the parameterization
326 // x = res[0] + res[1]*z
327 // y = res[2] + res[3]*z
328 // where x,y,z are NOT the lab axes but z is the lab axis along which the track
329 // has the largest lever arm and x,y are the remaining 2 axis in
330 // the order of fgkAxisID[z][0], fgkAxisID[z][1]
331 //
332 int np = fPntLast - fPntFirst + 1;
333 if (np<2) {
334 AliError("At least 2 points are needed for straight line fit");
335 return kFALSE;
336 }
337 //
338 if (fParAxis<0) SetParAxis(ChoseParAxis());
339 Double_t sZ=0,sZZ=0,sY=0,sYZ=0,sX=0,sXZ=0,det=0;
340 //
341 const float *coord[3] = {fPoints->GetX(),fPoints->GetY(),fPoints->GetZ()};
342 const Float_t *varZ = coord[ fParAxis ];
343 const Float_t *varX = coord[ fkAxID[kX] ];
344 const Float_t *varY = coord[ fkAxID[kY] ];
345 //
346 for (int i=fPntFirst;i<=fPntLast;i++) {
347 sZ += varZ[i];
348 sZZ += varZ[i]*varZ[i];
349 //
350 sX += varX[i];
351 sXZ += varX[i]*varZ[i];
352 //
353 sY += varY[i];
354 sYZ += varY[i]*varZ[i];
355 }
356 det = sZZ*np-sZ*sZ;
357 if (TMath::Abs(det)<fgkAlmostZero) return kFALSE;
358 fParams[0] = (sX*sZZ-sZ*sXZ)/det;
359 fParams[1] = (sXZ*np-sZ*sX)/det;
360 //
361 fParams[2] = (sY*sZZ-sZ*sYZ)/det;
362 fParams[3] = (sYZ*np-sZ*sY)/det;
363 //
364 return kTRUE;
365 //
366}
367
368//____________________________________________________
369void AliITSTPArrayFit::SetParAxis(Int_t ax)
370{
371 // select the axis which will be used as a parameter for the line: longest baseline
372 if (ax>kZ) {
373 AliInfo(Form("Wrong axis choice: %d",ax));
374 fParAxis = -1;
375 }
376 fParAxis = ax;
377 if (ax>=0) {
378 fkAxID = fgkAxisID[ax];
379 fkAxCID = fgkAxisCID[ax];
380 }
381 else {
382 fkAxID = fkAxCID = 0;
383 }
384 //
385}
386
387//____________________________________________________
388Int_t AliITSTPArrayFit::ChoseParAxis() const
389{
390 // select the variable with largest base as a parameter
391 Double_t cmn[3]={1.e9,1.e9,1.e9},cmx[3]={-1.e9,-1.e9,-1.e9};
392 //
393 const float *coord[3] = {fPoints->GetX(),fPoints->GetY(),fPoints->GetZ()};
394 for (int i=fPntFirst;i<=fPntLast;i++) {
395 for (int j=3;j--;) {
396 Double_t val = coord[j][i];
397 if (cmn[j]>val) cmn[j] = val;
398 if (cmx[j]<val) cmx[j] = val;
399 }
400 }
401 //
402 int axis = kZ;
403 if (cmx[axis]-cmn[axis] < cmx[kX]-cmn[kX]) axis = kX;
404 if (cmx[axis]-cmn[axis] < cmx[kY]-cmn[kY]) axis = kY;
405 return axis;
406 //
407}
408
409//____________________________________________________
410Double_t AliITSTPArrayFit::GetPosition(Double_t *xyzPCA, const Double_t *xyz, const Double_t *covI) const
411{
412 // calculate the position of the track at PCA to xyz
413 Double_t t = GetParPCA(xyz,covI);
414 GetPosition(xyzPCA,t);
415 return t;
416}
417
418//____________________________________________________
419Double_t AliITSTPArrayFit::GetPosition(Double_t *xyzPCA, const AliTrackPoint *pntCovInv) const
420{
421 // calculate the position of the track at PCA to pntCovInv
422 // NOTE: the covariance matrix of the point must be inverted
423 Double_t covI[6],xyz[3] = {pntCovInv->GetX(),pntCovInv->GetY(),pntCovInv->GetZ()};
424 for (int i=6;i--;) covI[i] = pntCovInv->GetCov()[i];
425 Double_t t = GetParPCA(xyz,covI);
426 GetPosition(xyzPCA,t);
427 return t;
428}
429
430//____________________________________________________
431void AliITSTPArrayFit::GetResiduals(Double_t *resPCA, const AliTrackPoint *pntCovInv) const
432{
433 // calculate the residuals of the track at PCA to pntCovInv
434 // NOTE: the covariance matrix of the point must be inverted
435 GetPosition(resPCA,pntCovInv);
436 resPCA[0] -= pntCovInv->GetX();
437 resPCA[1] -= pntCovInv->GetY();
438 resPCA[2] -= pntCovInv->GetZ();
439}
440
441//____________________________________________________
442void AliITSTPArrayFit::GetResiduals(Double_t *resPCA, const Double_t *xyz, const Double_t *covI) const
443{
444 // calculate the residuals of the track at PCA to xyz
445 GetPosition(resPCA,xyz,covI);
446 resPCA[kX] -= xyz[kX];
447 resPCA[kY] -= xyz[kY];
448 resPCA[kZ] -= xyz[kZ];
449}
450
451//____________________________________________________
452Double_t AliITSTPArrayFit::GetParPCALine(const Double_t *xyz, const Double_t *covI) const
453{
454 // get parameter for the point with least weighted distance to the point
455 //
456 Double_t rhs,denom;
457 Double_t dx = fParams[kA0]-xyz[ fkAxID[kX] ];
458 Double_t dy = fParams[kA1]-xyz[ fkAxID[kY] ];
459 Double_t dz = -xyz[ fkAxID[kZ] ];
460 //
461 if (covI) {
462 Double_t tx = fParams[kB0]*covI[ fkAxCID[kXX] ] + fParams[kB1]*covI[ fkAxCID[kXY] ] + covI[ fkAxCID[kXZ] ];
463 Double_t ty = fParams[kB0]*covI[ fkAxCID[kXY] ] + fParams[kB1]*covI[ fkAxCID[kYY] ] + covI[ fkAxCID[kYZ] ];
464 Double_t tz = fParams[kB0]*covI[ fkAxCID[kXZ] ] + fParams[kB1]*covI[ fkAxCID[kYZ] ] + covI[ fkAxCID[kZZ] ];
465 rhs = tx*dx + ty*dy + tz*dz;
466 denom = -(fParams[kB0]*(covI[ fkAxCID[kXZ] ] + tx) + fParams[kB1]*(covI[ fkAxCID[kYZ] ] + ty) + covI[ fkAxCID[kZZ] ]);
467 }
468 else {
469 rhs = fParams[kB0]*dx + fParams[kB1]*dy + dz;
470 denom = -(fParams[kB0]*fParams[kB0] + fParams[kB1]*fParams[kB1] + 1);
471 }
472 //
473 return rhs/denom;
474 //
475}
476
477//____________________________________________________
478void AliITSTPArrayFit::GetDResDPosLine(Double_t *dXYZdP, /*const Double_t *xyz,*/ const Double_t *covI) const
479{
480 // calculate detivative of the PCA residuals vs point position and fill in user provide
481 // array in the format {dXdXp,dY/dXp,dZdXp, ... dXdZp,dYdZp,dZdZp}
482 //
483 Double_t dTdP[3];
484 GetDtDPosLine(dTdP, /*xyz,*/ covI); // derivative of the t-param over point position
485 //
486 for (int i=3;i--;) {
487 int var = fkAxID[i];
488 Double_t *curd = dXYZdP + var*3; // d/dCoord_i
489 curd[ fkAxID[kX] ] = fParams[kB0]*dTdP[var];
490 curd[ fkAxID[kY] ] = fParams[kB1]*dTdP[var];
491 curd[ fkAxID[kZ] ] = dTdP[var];
492 curd[ var ]-= 1.;
493 }
494 //
495}
496
497//____________________________________________________
498void AliITSTPArrayFit::GetDResDParamsLine(Double_t *dXYZdP, const Double_t *xyz, const Double_t *covI) const
499{
500 // calculate detivative of the PCA residuals vs line parameters and fill in user provide
501 // array in the format {dXdP0,dYdP0,dZdP0, ... dXdPn,dYdPn,dZdPn}
502 //
503 Double_t dTdP[4];
504 Double_t t = GetDtDParamsLine(dTdP, xyz, covI); // derivative of the t-param over line params
505 //
506 Double_t *curd = dXYZdP + kA0*3; // d/dA0
507 curd[ fkAxID[kX] ] = fParams[kB0]*dTdP[kA0] + 1.;
508 curd[ fkAxID[kY] ] = fParams[kB1]*dTdP[kA0];
509 curd[ fkAxID[kZ] ] = dTdP[kA0];
510 //
511 curd = dXYZdP + kB0*3; // d/dB0
512 curd[ fkAxID[kX] ] = fParams[kB0]*dTdP[kB0] + t;
513 curd[ fkAxID[kY] ] = fParams[kB1]*dTdP[kB0];
514 curd[ fkAxID[kZ] ] = dTdP[kB0];
515 //
516 curd = dXYZdP + kA1*3; // d/dA1
517 curd[ fkAxID[kX] ] = fParams[kB0]*dTdP[kA1];
518 curd[ fkAxID[kY] ] = fParams[kB1]*dTdP[kA1] + 1.;
519 curd[ fkAxID[kZ] ] = dTdP[kA1];
520 //
521 curd = dXYZdP + kB1*3; // d/dB1
522 curd[ fkAxID[kX] ] = fParams[kB0]*dTdP[kB1];
523 curd[ fkAxID[kY] ] = fParams[kB1]*dTdP[kB1] + t;
524 curd[ fkAxID[kZ] ] = dTdP[kB1];
525 //
526}
527
528//____________________________________________________
529Double_t AliITSTPArrayFit::GetDtDParamsLine(Double_t *dtparam,const Double_t *xyz, const Double_t *covI) const
530{
531 // get t-param detivative over the parameters for the point with least weighted distance to the point
532 //
533 Double_t rhs,denom;
534 Double_t dx = fParams[kA0]-xyz[ fkAxID[kX] ];
535 Double_t dy = fParams[kA1]-xyz[ fkAxID[kY] ];
536 Double_t dz = -xyz[ fkAxID[kZ] ];
537 Double_t rhsDA0,rhsDA1,rhsDB0,rhsDB1,denDB0,denDB1;
538 //
539 if (covI) {
540 Double_t tx = fParams[kB0]*covI[ fkAxCID[kXX] ] + fParams[kB1]*covI[ fkAxCID[kXY] ] + covI[ fkAxCID[kXZ] ];
541 Double_t ty = fParams[kB0]*covI[ fkAxCID[kXY] ] + fParams[kB1]*covI[ fkAxCID[kYY] ] + covI[ fkAxCID[kYZ] ];
542 Double_t tz = fParams[kB0]*covI[ fkAxCID[kXZ] ] + fParams[kB1]*covI[ fkAxCID[kYZ] ] + covI[ fkAxCID[kZZ] ];
543 rhs = tx*dx + ty*dy + tz*dz;
544 denom = -(fParams[kB0]*(covI[ fkAxCID[kXZ] ] + tx) + fParams[kB1]*(covI[ fkAxCID[kYZ] ] + ty) + covI[ fkAxCID[kZZ] ]);
545 //
546 rhsDA0 = tx;
547 rhsDA1 = ty;
548 rhsDB0 = covI[ fkAxCID[kXX] ]*dx + covI[ fkAxCID[kXY] ]*dy + covI[ fkAxCID[kXZ] ]*dz;
549 rhsDB1 = covI[ fkAxCID[kXY] ]*dx + covI[ fkAxCID[kYY] ]*dy + covI[ fkAxCID[kYZ] ]*dz;
550 //
551 denDB0 = -(tx + tx);
552 denDB1 = -(ty + ty);
553 }
554 else {
555 rhs = fParams[kB0]*dx + fParams[kB1]*dy + dz;
556 denom = -(fParams[kB0]*fParams[kB0] + fParams[kB1]*fParams[kB1] + 1);
557 //
558 rhsDA0 = fParams[kB0];
559 rhsDB0 = dx;
560 rhsDA1 = fParams[kB1];
561 rhsDB1 = dy;
562 //
563 denDB0 = -(fParams[kB0]+fParams[kB0]);
564 denDB1 = -(fParams[kB1]+fParams[kB1]);
565 //
566 }
567 //
568 Double_t denom2 = denom*denom;
569 dtparam[kA0] = rhsDA0/denom; // denom does not depend on A0,A1
570 dtparam[kA1] = rhsDA1/denom;
571 dtparam[kB0] = rhsDB0/denom - rhs/denom2 * denDB0;
572 dtparam[kB1] = rhsDB1/denom - rhs/denom2 * denDB1;
573 //
574 return rhs/denom;
575}
576
577//____________________________________________________
578void AliITSTPArrayFit::GetDtDPosLine(Double_t *dtpos,/*const Double_t *xyz,*/ const Double_t *covI) const
579{
580 // get t-param detivative over the parameters for the point with least weighted distance to the point
581 //
582 // Double_t rhs;
583 // Double_t dx = fParams[kA0]-xyz[ fkAxID[kX] ];
584 // Double_t dy = fParams[kA1]-xyz[ fkAxID[kY] ];
585 // Double_t dz = -xyz[ fkAxID[kZ] ];
586 Double_t denom;
587 Double_t rhsDX,rhsDY,rhsDZ;
588 //
589 if (covI) {
590 Double_t tx = fParams[kB0]*covI[ fkAxCID[kXX] ] + fParams[kB1]*covI[ fkAxCID[kXY] ] + covI[ fkAxCID[kXZ] ];
591 Double_t ty = fParams[kB0]*covI[ fkAxCID[kXY] ] + fParams[kB1]*covI[ fkAxCID[kYY] ] + covI[ fkAxCID[kYZ] ];
592 Double_t tz = fParams[kB0]*covI[ fkAxCID[kXZ] ] + fParams[kB1]*covI[ fkAxCID[kYZ] ] + covI[ fkAxCID[kZZ] ];
593 // rhs = tx*dx + ty*dy + tz*dz;
594 denom = -(fParams[kB0]*(covI[ fkAxCID[kXZ] ] + tx) + fParams[kB1]*(covI[ fkAxCID[kYZ] ] + ty) + covI[ fkAxCID[kZZ] ]);
595 //
596 rhsDX = -tx;
597 rhsDY = -ty;
598 rhsDZ = -tz;
599 }
600 else {
601 // rhs = fParams[kB0]*dx + fParams[kB1]*dy + dz;
602 denom = -(fParams[kB0]*fParams[kB0] + fParams[kB1]*fParams[kB1] + 1);
603 //
604 rhsDX = -fParams[kB0];
605 rhsDY = -fParams[kB1];
606 rhsDZ = -1;
607 //
608 }
609 //
610 dtpos[ fkAxID[kX] ] = rhsDX/denom;
611 dtpos[ fkAxID[kY] ] = rhsDY/denom;
612 dtpos[ fkAxID[kZ] ] = rhsDZ/denom;
613 //
614 // return rhs/denom;
615}
616
617//____________________________________________________
618void AliITSTPArrayFit::GetDResDParamsLine(Double_t *dXYZdP, Int_t ipnt) const
619{
620 // calculate detivative of the PCA residuals vs line parameters and fill in user provide
621 // array in the format {dXdP0,dYdP0,dZdP0, ... dXdPn,dYdPn,dZdPn}
622 //
623 if (ipnt<fPntFirst || ipnt>fPntLast) {
624 AliError(Form("Attempt to access the point %d not in the fitted points [%d:%d]",ipnt,fPntFirst,fPntLast));
625 return;
626 }
627 GetDResDParamsLine(dXYZdP, GetPoint(ipnt) , IsCovIgnored() ? 0 : GetCovI(ipnt));
628}
629
630//____________________________________________________
631void AliITSTPArrayFit::GetDResDPosLine(Double_t *dXYZdP, Int_t ipnt) const
632{
633 // calculate detivative of the PCA residuals vs point position and fill in user provide
634 // array in the format {dXdXp,dY/dXp,dZdXp, ... dXdZp,dYdZp,dZdZp}
635 //
636 if (ipnt<fPntFirst || ipnt>fPntLast) {
637 AliError(Form("Attempt to access the point %d not in the fitted points [%d:%d]",ipnt,fPntFirst,fPntLast));
638 return;
639 }
640 GetDResDPosLine(dXYZdP,IsCovIgnored() ? 0 : GetCovI(ipnt));
641}
642
643//____________________________________________________
644void AliITSTPArrayFit::GetDResDParams(Double_t *dXYZdP, Int_t ipnt)
645{
646 // calculate detivative of the PCA residuals vs track parameters and fill in user provide
647 // array in the format {dXdP0,dYdP0,dZdP0, ... dXdPn,dYdPn,dZdPn}
648 //
649 if (ipnt<fPntFirst || ipnt>fPntLast) {
650 AliError(Form("Attempt to access the point %d not in the fitted points [%d:%d]",ipnt,fPntFirst,fPntLast));
651 return;
652 }
653 GetDResDParams(dXYZdP, GetPoint(ipnt) , IsCovIgnored() ? 0 : GetCovI(ipnt));
654}
655
656//____________________________________________________
657void AliITSTPArrayFit::GetDResDPos(Double_t *dXYZdP, Int_t ipnt)
658{
659 // calculate detivative of the PCA residuals vs point position and fill in user provide
660 // array in the format {dXdXp,dY/dXp,dZdXp, ... dXdZp,dYdZp,dZdZp}
661 //
662 if (ipnt<fPntFirst || ipnt>fPntLast) {
663 AliError(Form("Attempt to access the point %d not in the fitted points [%d:%d]",ipnt,fPntFirst,fPntLast));
664 return;
665 }
666 GetDResDPos(dXYZdP, GetPoint(ipnt), IsCovIgnored() ? 0 : GetCovI(ipnt));
667}
668
669//____________________________________________________
670void AliITSTPArrayFit::GetDResDParams(Double_t *dXYZdP, const Double_t *xyz, const Double_t *covI)
671{
672 // get residual detivatives over the track parameters for the point with least weighted distance to the point
673 //
674 if (!IsFieldON()) { // for the straight line calculate analytically
675 GetDResDParamsLine(dXYZdP, xyz, covI);
676 return;
677 }
678 //
679 // calculate derivative numerically
680 const Double_t delta = 0.01;
681 Double_t xyzVar[4][3];
682 //
683 for (int ipar = 5;ipar--;) {
684 double sav = fParams[ipar];
685 fParams[ipar] -= delta;
686 GetPosition(xyzVar[0],xyz,covI);
687 fParams[ipar] += delta/2;
688 GetPosition(xyzVar[1],xyz,covI);
689 fParams[ipar] += delta;
690 GetPosition(xyzVar[2],xyz,covI);
691 fParams[ipar] += delta/2;
692 GetPosition(xyzVar[3],xyz,covI);
693 fParams[ipar] = sav; // restore
694 //
695 double *curd = dXYZdP + 3*ipar;
696 for (int i=3;i--;) curd[i] = (8.*(xyzVar[2][i]-xyzVar[1][i]) - (xyzVar[3][i]-xyzVar[0][i]))/6./delta;
697 }
698 //
699}
700
701
702//____________________________________________________
703void AliITSTPArrayFit::GetDResDPos(Double_t *dXYZdP, const Double_t *xyz, const Double_t *covI)
704{
705 // get residuals detivative over the point position for the point with least weighted distance to the point
706 //
707
708 if (!IsFieldON()) { // for the straight line calculate analytically
709 GetDResDPosLine(dXYZdP, /*xyz,*/ covI);
710 return;
711 }
712 //
713 // calculate derivative numerically
714 const Double_t delta = 0.005;
715 Double_t xyzVar[4][3];
716 Double_t xyzv[3] = {xyz[0],xyz[1],xyz[2]};
717 //
718 for (int ipar = 3;ipar--;) {
719 double sav = xyzv[ipar];
720 xyzv[ipar] -= delta;
721 GetPosition(xyzVar[0],xyzv,covI);
722 xyzv[ipar] += delta/2;
723 GetPosition(xyzVar[1],xyzv,covI);
724 xyzv[ipar] += delta;
725 GetPosition(xyzVar[2],xyzv,covI);
726 xyzv[ipar] += delta/2;
727 GetPosition(xyzVar[3],xyzv,covI);
728 xyzv[ipar] = sav; // restore
729 //
730 double *curd = dXYZdP + 3*ipar;
731 for (int i=3;i--;) curd[i] = (8.*(xyzVar[2][i]-xyzVar[1][i]) - (xyzVar[3][i]-xyzVar[0][i]))/6./delta;
732 curd[ipar] -= 1.;
733 }
734 //
735}
736
737//________________________________________________________________________________________________________
738Double_t AliITSTPArrayFit::GetParPCAHelix(const Double_t* xyz, const Double_t* covI) const
739{
740 // find track parameter t (eq.2) corresponding to point of closest approach to xyz
741 //
742 Double_t phi = GetParPCACircle(xyz[kX],xyz[kY]);
743 Double_t cs = TMath::Cos(fParams[kPhi0]);
744 Double_t sn = TMath::Sin(fParams[kPhi0]);
745 Double_t xc = (fParams[kD0]+fParams[kR0])*cs;
746 Double_t yc = (fParams[kD0]+fParams[kR0])*sn;
747 Double_t dchi2,ddchi2;
748 //
749 Double_t dzD = -fParams[kR0]*fParams[kDip];
750 Double_t dphi = 0;
751 //
752 int it=0;
753 do {
754 cs = TMath::Cos(phi + fParams[kPhi0]);
755 sn = TMath::Sin(phi + fParams[kPhi0]);
756 //
757 Double_t dxD = fParams[kR0]*sn;
758 Double_t dyD = -fParams[kR0]*cs;
759 Double_t dxDD = -dyD;
760 Double_t dyDD = dxD;
761 //
762 Double_t dx = xc - fParams[kR0]*cs - xyz[kX];
763 Double_t dy = yc - fParams[kR0]*sn - xyz[kY];
764 Double_t dz = fParams[kDZ] + dzD*phi- xyz[kZ];
765 //
766 if (covI) {
767 Double_t tx = dx*covI[kXX] + dy*covI[kXY] + dz*covI[kXZ];
768 Double_t ty = dx*covI[kXY] + dy*covI[kYY] + dz*covI[kYZ];
769 Double_t tz = dx*covI[kXZ] + dy*covI[kYZ] + dz*covI[kZZ];
770 //
771 Double_t ttx = dxD*covI[kXX] + dyD*covI[kXY] + dzD*covI[kXZ];
772 Double_t tty = dxD*covI[kXY] + dyD*covI[kYY] + dzD*covI[kYZ];
773 Double_t ttz = dxD*covI[kXZ] + dyD*covI[kYZ] + dzD*covI[kZZ];
774 //
775 // chi2 = dx*tx + dy*ty + dz*tz;
776 dchi2 = dxD*tx + dyD*ty + dzD*tz;
777 ddchi2 = dxDD*tx + dyDD*ty + dxD *ttx + dyD *tty + dzD *ttz;
778 //
779 }
780 else {
781 // chi2 = dx*dx + dy*dy + dz*dz;
782 dchi2 = dxD*dx + dyD*dy + dzD*dz;
783 ddchi2 = dxDD*dx + dyDD*dy + + dxD*dxD + dyD*dyD + dzD*dzD;
784 }
785 //
786 if (TMath::Abs(ddchi2)<fgkAlmostZero || TMath::Abs(dphi=dchi2/ddchi2)<fEps) break;
787 phi -= dphi;
788 } while(++it<fMaxIter);
789 //
790 return phi;
791}
792
793//________________________________________________________________________________________________________
794Double_t AliITSTPArrayFit::GetParPCACircle(Double_t x,Double_t y) const
795{
796 // find track parameter t (eq.2) corresponding to point on the circle with closest approach to x,y
797 //
798 Double_t r = fParams[kD0]+fParams[kR0];
799 Double_t t = TMath::ATan2( r*TMath::Sin(fParams[kPhi0])-y, r*TMath::Cos(fParams[kPhi0])-x ) - fParams[kPhi0];
800 if (fParams[kR0] < 0) t += TMath::Pi();
801 if (t > TMath::Pi()) t -= TMath::Pi()*2;
802 if (t <-TMath::Pi()) t += TMath::Pi()*2;
803 return t;
804}
805
806//________________________________________________________________________________________________________
807Double_t AliITSTPArrayFit::GetHelixParAtR(Double_t r) const
808{
809 // find helix parameter t (eq.2) corresponding to point on the circle of radius t
810 //
811 double gam = 1. - (r-fParams[kD0])*(r+fParams[kD0])/fParams[kR0]/(fParams[kD0]+fParams[kR0])/2.;
812 return (TMath::Abs(gam)>1) ? -1e9 : TMath::ACos(gam);
813}
814
815//________________________________________________________________________________________________________
816Double_t AliITSTPArrayFit::CalcChi2NDF() const
817{
818 // calculate fit chi2/ndf
819 Double_t chi2 = 0;
820 Double_t dr[3]; // residuals
821 //if (!IsFitDone()) return -1;
822 for (int ipnt=fPntFirst;ipnt<=fPntLast;ipnt++) {
823 GetResiduals(dr,ipnt);
824 Double_t* covI = GetCovI(ipnt);
825 chi2 += dr[kX]*(dr[kX]*covI[ kXX ]+dr[kY]*covI[ kXY ]+dr[kZ]*covI[ kXZ ])
826 + dr[kY]*(dr[kX]*covI[ kXY ]+dr[kY]*covI[ kYY ]+dr[kZ]*covI[ kYZ ])
827 + dr[kZ]*(dr[kX]*covI[ kXZ ]+dr[kY]*covI[ kYZ ]+dr[kZ]*covI[ kZZ ]);
828 }
829 int ndf = (fPntLast-fPntFirst+1)*3 - GetNParams();
830 chi2 /= ndf;
831 return chi2;
832}
833
834//________________________________________________________________________________________________________
835void AliITSTPArrayFit::GetResiduals(Double_t *res,Int_t ipnt) const
836{
837 // calculate residuals at point
838 if (ipnt<fPntFirst || ipnt>fPntLast) {
839 AliError(Form("Attempt to access the point %d not in the fitted points [%d:%d]",ipnt,fPntFirst,fPntLast));
840 return;
841 }
842 GetPosition(res,fCurT[ipnt]);
843 res[kX] -= fPoints->GetX()[ipnt];
844 res[kY] -= fPoints->GetY()[ipnt];
845 res[kZ] -= fPoints->GetZ()[ipnt];
846}
847
848//________________________________________________________________________________________________________
849void AliITSTPArrayFit::GetPosition(Double_t *xyz, Double_t t) const
850{
851 // calculate track position for parameter value t
852 if (IsFieldON()) {
853 //
854 Double_t rrho = fParams[kD0]+fParams[kR0];
855 Double_t xc = rrho*TMath::Cos(fParams[kPhi0]);
856 Double_t yc = rrho*TMath::Sin(fParams[kPhi0]);
857 Double_t r = fParams[kR0];
858 Double_t ze = 0;
859 //
860 if (IsELossON()) {
861 if (t>0) {
862 for (int i=fFirstPosT;i<fNElsPnt;i++) { // along the track direction
863 int indE = fElsId[i];
864 if ( t<fCurT[indE] ) break; // does not reach this layer on its way to t
865 xc += fElsDR[indE] * TMath::Cos(fParams[kPhi0] + fCurT[indE]);
866 yc += fElsDR[indE] * TMath::Sin(fParams[kPhi0] + fCurT[indE]);
867 ze += fElsDR[indE] * fCurT[indE];
868 r += fElsDR[indE];
869 //printf("ELoss@ %+.2e r:%+.3e got %+.3e\n",fCurT[indE],r,fElsDR[indE]);
870 }
871 } else {
872 for (int i=fFirstPosT;i--;) { // against the track direction
873 int indE = fElsId[i];
874 if ( t>=fCurT[indE] ) break; // does not reach this layer on its way to t
875 xc += fElsDR[indE] * TMath::Cos(fParams[kPhi0] + fCurT[indE]);
876 yc += fElsDR[indE] * TMath::Sin(fParams[kPhi0] + fCurT[indE]);
877 ze += fElsDR[indE] * fCurT[indE];
878 r += fElsDR[indE];
879 //printf("ELoss@ %+.2e r:%+.3e got %+.3e\n",fCurT[indE],r,fElsDR[indE]);
880 }
881 }
882 }
883 //
884 xyz[kZ] = fParams[kDZ] - fParams[kDip]*(t*r - ze);
885 //
886 t += fParams[kPhi0];
887 xyz[kX] = xc - r*TMath::Cos(t);
888 xyz[kY] = yc - r*TMath::Sin(t);
889 // printf("t: %+.3e xyz:%+.2e %+.2e %+.2e | R %+.6e -> %+.6e | sign %d\n",t-fParams[kPhi0],xyz[0],xyz[1],xyz[2],fParams[kR0],r,GetSignQB());
890 }
891 else {
892 xyz[ fkAxID[kX] ] = fParams[kA0] + fParams[kB0]*t;
893 xyz[ fkAxID[kY] ] = fParams[kA1] + fParams[kB1]*t;
894 xyz[ fParAxis ] = t;
895 }
896}
897
898//________________________________________________________________________________________________________
899void AliITSTPArrayFit::GetDirCos(Double_t *dircos, Double_t t) const
900{
901 // calculate track direction cosines for parameter value t
902 if (IsFieldON()) {
903 dircos[kZ] = -fParams[kDip];
904 t += fParams[kPhi0];
905 dircos[kX] = TMath::Sin(t);
906 dircos[kY] =-TMath::Cos(t);
907 double gam = TMath::Sign(1/TMath::Sqrt(dircos[kZ]*dircos[kZ]+dircos[kY]*dircos[kY]+dircos[kX]*dircos[kX]),fParams[kR0]);
908 for (int i=3;i--;) dircos[i] *= gam;
66214d86 909 if (GetSignQB()>0) for (int i=3;i--;) dircos[i] = -dircos[i]; // positive tracks move along decreasing t
6be22b3f 910 }
911 else {
912 double gam = 1/TMath::Sqrt( fParams[kB0]*fParams[kB0] + fParams[kB1]*fParams[kB1] + 1.);
913 dircos[ fkAxID[kX] ] = fParams[kB0]*gam;
914 dircos[ fkAxID[kY] ] = fParams[kB1]*gam;
915 dircos[ fParAxis ] = gam;
66214d86 916 // decide direction
917 if (IsTypeCollision()) {
918 static double xyzF[3],xyzL[3];
919 GetPosition(xyzF,fPntFirst);
920 GetPosition(xyzL,fPntLast);
921 double dif = fCurT[fPntLast] - fCurT[fPntFirst];
922 double dr = (xyzL[kX]-xyzF[kX])*(xyzL[kX]+xyzF[kX]) + (xyzL[kY]-xyzF[kY])*(xyzL[kY]+xyzF[kY]);
923 if (dr*dif<0) for (int i=3;i--;) dircos[i] = -dircos[i]; // with increasing t the tracks comes closer to origin
924 }
925 else if (dircos[kY]>0) for (int i=3;i--;) dircos[i] = -dircos[i]; // cosmic tracks have negative angle to Y axis
6be22b3f 926 }
66214d86 927 //
6be22b3f 928}
929
930//________________________________________________________________________________________________________
931Double_t AliITSTPArrayFit::GetMachinePrec()
932{
933 // estimate machine precision
934 Double_t eps=1.0,a;
935 do { a = 1. + (eps=eps/2.0); } while(a>1.);
936 return TMath::Abs(2.*eps);
937}
938
939//________________________________________________________________________________________________________
940Bool_t AliITSTPArrayFit::FitHelixCrude(Int_t extQ)
941{
942 // crude estimate of helix parameters, w/o errors and Eloss.
943 // 1st fit the circle (R,xc,yc) by minimizing
944 // chi2 = sum{ (bx*xi + by*yi + xi^2+yi^2 + rho)^2 } vs bx,by,rho
945 // with bx = -2*xc, by = -2*yc , rho = xc^2+yc^2 - R2
946 //
947 // if charge is not imposed (extQ==0) then it will be determined from the collision type
948 //
949 Bool_t eloss = IsELossON();
950 //
951 int np = fPntLast - fPntFirst + 1;
1d06ac63 952 if (np<3) { AliError("At least 3 points are needed for helix fit"); return kFALSE; }
6be22b3f 953 //
954 const float *x=fPoints->GetX(),*y=fPoints->GetY(),*z=fPoints->GetZ(),*cov=fPoints->GetCov();
955 //
956 // linear circle fit --------------------------------------------------- >>>
957 Double_t sxx=0,sxy=0,syy=0,sx=0,sy=0,rhs0=0,rhs1=0,rhs2=0,minR=1E9;
958 int minRId = 0;
959 for (int i=fPntFirst;i<=fPntLast;i++) {
960 Double_t xx = x[i]*x[i];
961 Double_t yy = y[i]*y[i];
962 Double_t xy = x[i]*y[i];
963 Double_t xxyy = xx + yy;
964 //
965 sxx += xx;
966 sxy += xy;
967 syy += yy;
968 sx += x[i];
969 sy += y[i];
970 //
971 rhs0 -= xxyy*x[i];
972 rhs1 -= xxyy*y[i];
973 rhs2 -= xxyy;
974 //
975 // remember Id of the point closest to origin, to determine the charge
976 if (xxyy<minR) { minR = xxyy; minRId = i; }
977 //
978 if (eloss) { // find layer id
979 int lrid,volid = fPoints->GetVolumeID()[i];
980 if (volid>0) lrid = fgkActiveLrITS[AliGeomManager::VolUIDToLayer(fPoints->GetVolumeID()[i])-1];
981 else { // missing layer info, find from radius
982 double r = TMath::Sqrt(xxyy);
983 for (lrid=kMaxLrITS;lrid--;) if ( IsZero(r-fgkRLayITS[ lrid ],1.) ) break;
984 }
985 fElsDR[i] = (lrid>=0 && lrid<kMaxLrITS) ? fgRhoLITS[ lrid ] : 0; // eloss for normal track
986 }
987 //
988 }
989 //
990 Double_t mn00 = syy*np-sy*sy;
991 Double_t mn01 = sxy*np-sy*sx;
992 Double_t mn02 = sxy*sy-syy*sx;
993 Double_t det = sxx*mn00 - sxy*mn01 + sx*mn02;
994 if (TMath::Abs(det)<fgkAlmostZero) return kFALSE;
995 //
996 Double_t mn11 = sxx*np-sx*sx;
997 Double_t mn12 = sxx*sy-sxy*sx;
998 Double_t mn22 = sxx*syy-sxy*sxy;
999 //
1000 Double_t mi00 = mn00/det;
1001 Double_t mi01 = -mn01/det;
1002 Double_t mi02 = mn02/det;
1003 Double_t mi11 = mn11/det;
1004 Double_t mi12 = -mn12/det;
1005 Double_t mi22 = mn22/det;
1006 //
1007 Double_t xc = -(rhs0*mi00 + rhs1*mi01 + rhs2*mi02)/2;
1008 Double_t yc = -(rhs0*mi01 + rhs1*mi11 + rhs2*mi12)/2;
1009 Double_t rho2 = (rhs0*mi02 + rhs1*mi12 + rhs2*mi22);
1010 //
1d06ac63 1011 Double_t rad = xc*xc + yc*yc - rho2;
6be22b3f 1012 rad = (rad>fgkAlmostZero) ? (TMath::Sqrt(rad)):fgkAlmostZero;
1013 //
1014 // printf("Rad: %+e xc: %+e yc: %+e\n",rad,xc,yc);
1d06ac63 1015
6be22b3f 1016 // linear circle fit --------------------------------------------------- <<<
1017 //
1018 // decide sign(Q*B) and fill cicrle parameters ------------------------- >>>
1019 int sqb;
1020 if (extQ) {
1021 SetCharge(extQ);
1022 sqb = fBz<0 ? -GetCharge():GetCharge();
1023 }
1024 else {
1025 // determine the charge from the collision type and field sign
1026 // the negative Q*B will have positive Vc x V0 product Z component
1027 // with Vc={-xc,-yc} : vector from circle center to the origin
1028 // and V0 - track direction vector (take {0,-1,1} for cosmics)
1029 // If Bz is not provided, assume positive Bz
1030 sqb = ( IsTypeCosmics() ? xc:(yc*x[minRId]-xc*y[minRId]) ) > 0 ? -1:1;
1031 SetCharge( fBz<0 ? -sqb : sqb);
1032 }
1033 //
6be22b3f 1034 Double_t phi = TMath::ATan2(yc,xc);
1035 if (sqb<0) phi += TMath::Pi();
1036 if (phi > TMath::Pi()) phi -= 2.*TMath::Pi();
1037 else if (phi <-TMath::Pi()) phi += 2.*TMath::Pi();
1038 fParams[kPhi0] = phi;
1039 fParams[kR0] = sqb<0 ? -rad:rad;
1d06ac63 1040 fParams[kD0] = xc*TMath::Cos(phi) + yc*TMath::Sin(phi) - fParams[kR0];
6be22b3f 1041 //
1042 // decide sign(Q*B) and fill cicrle parameters ------------------------- <<<
1043 //
1044 // find z-offset and dip + the parameter t of closest approach to hits - >>>
1045 //
1046 UInt_t hitLrPos=0; // pattern of hit layers at pos
1047 UInt_t hitLrNeg=0; // and negative t's
1048
1049 Double_t ss=0,st=0,sz=0,stt=0,szt=0;
1050 for (int i=fPntFirst;i<=fPntLast;i++) {
1051 //
1052 Double_t ze2 = cov[i*6 + kZZ];
1053 Double_t t = TMath::ATan2(yc-y[i],xc-x[i]) - fParams[kPhi0]; // angle at measured z
1054 if (fParams[kR0]<0) t += TMath::Pi();
1055 if (t > TMath::Pi()) t -= TMath::Pi()*2;
1056 else if (t <-TMath::Pi()) t += TMath::Pi()*2;
1057 if (ze2<fgkAlmostZero) ze2 = 1E-8;
1058 ze2 = 1./ze2;
1059 ss += ze2;
1060 st += t*ze2;
1061 stt+= t*t*ze2;
1062 sz += z[i]*ze2;
1063 szt+= z[i]*t*ze2;
1064 //
1065 fCurT[i] = t; // parameter of the closest approach to the point
1066 // printf("%d %+e %+e %+e %+e\n",i,x[i],y[i],z[i],t);
1067 if (eloss) {
1068 double r = TMath::Sqrt(x[i]*x[i]+y[i]*y[i]);
1069 int lr;
1070 for (lr=kMaxLrITS;lr--;) if ( IsZero(r-fgkRLayITS[ lr ],1.) ) break;
1071 if (lr<kMaxLrITS) {
1072 if (t>0) hitLrPos |= (1<<lr); // set bit of the layer
1073 else hitLrNeg |= (1<<lr); // set bit of the layer
1074 }
1075 }
1076 }
1077 det = ss*stt - st*st;
1078 if (TMath::Abs(det)<fgkAlmostZero) { // no Z dependence
1079 fParams[kDZ] = sz/ss;
1080 fParams[kDip] = 0;
1081 }
1082 else {
1083 fParams[kDZ] = (sz*stt-st*szt)/det;
1084 fParams[kDip] = -(ss*szt-st*sz)/det/fParams[kR0];
1085 }
1086 //
1087 // find z-offset and dip + the parameter t of closest approach to hits - <<<
1088 //
1089 // fill info needed to account for ELoss ------------------------------- >>>
1090 if (eloss) {
1091 fNElsPnt = fPntLast - fPntFirst + 1;
1092 //
1093 // to account for the energy loss in the passive volumes, calculate the relevant t-parameters
1094 double* tcur = fCurT + fPntFirst;
1095 double* ecur = fElsDR+ fPntFirst;
1096 //
1097 for (int ilp=3;ilp--;) {
1098 int id = fgkPassivLrITS[ilp];
1099 double tp = GetHelixParAtR( fgkRLayITS[ id ] );
1100 if (tp<0) continue; // does not hit this radius
1101 //
1102 tcur[fNElsPnt] = GetSignQB()>0 ? -tp : tp;
1103 ecur[fNElsPnt] = fgRhoLITS[ id ];
1104 fNElsPnt++;
1105 // printf("Passive on lr %d %+e\n",ilp,tcur[fNElsPnt-1]);
1106 //
1107 if (IsTypeCosmics() && !IsZero(tp)) { // 2 crossings for cosmics
1108 tcur[fNElsPnt] = -tcur[fNElsPnt-1];
1109 ecur[fNElsPnt] = ecur[fNElsPnt-1];
1110 fNElsPnt++;
1111 //printf("Passive* on lr %d %+e\n",ilp,-tcur[fNElsPnt-1]);
1112 }
1113 //
1114 }
1115 // check if some active layers did not miss the hit, treat them as passive
1116 for (int ilp=6;ilp--;) {
1117 int id = fgkActiveLrITS[ilp];
1118 double tp = GetHelixParAtR( fgkRLayITS[ id ] );
1119 if (tp<0) continue; // does not hit this radius
1120 //
1121 if ( (GetSignQB()>0||IsTypeCosmics()) && !(hitLrNeg & (1<<id)) ) {
1122 tcur[fNElsPnt] = -tp;
1123 ecur[fNElsPnt] = fgRhoLITS[ id ];
1124 fNElsPnt++;
1125 //printf("Missed on lr %d %+e\n",ilp,-tp);
1126 }
1127 //
1128 if ( (GetSignQB()<0||IsTypeCosmics()) && !(hitLrPos & (1<<id)) ) {
1129 tcur[fNElsPnt] = tp;
1130 ecur[fNElsPnt] = fgRhoLITS[ id ];
1131 fNElsPnt++;
1132 //printf("Missed* on lr %d %e\n",ilp,tp);
1133 }
1134 }
1135 //
1136 TMath::Sort(fNElsPnt,fCurT+fPntFirst,fElsId,kFALSE); // index e-loss points in increasing order
1137 // find the position of smallest positive t-param
1138 for (fFirstPosT=0;fFirstPosT<fNElsPnt;fFirstPosT++) if (fCurT[ fElsId[ fFirstPosT ] ]>0) break;
1139 //
1140 Double_t cdip = 1./TMath::Sqrt(1.+fParams[kDip]*fParams[kDip]);
1141 Double_t ptot = TMath::Abs(fParams[kR0]*fgkCQConv*fBz/cdip); // momentum and energy
1142 Double_t etot = TMath::Sqrt(ptot*ptot + fMass*fMass); // in the point of closest approach to beam
1143 Double_t normS[3];
1144 //
1145 // Positive t-params: along the track direction for negative track, against for positive
1146 Double_t pcur = ptot, ecurr = etot;
1147 for (int ip=fFirstPosT;ip<fNElsPnt;ip++) {
1148 int tID = fElsId[ip];
1149 Double_t t = fCurT[ tID ];
1150 //
1151 if (tID>fPntLast) { // this is not a hit layer but passive layer
1152 double php = TMath::ATan2(yc-fParams[kR0]*TMath::Cos(fParams[kPhi0]+t),
1153 xc-fParams[kR0]*TMath::Cos(fParams[kPhi0]+t));
1154 normS[0] = -TMath::Cos(php); // normal to the cylinder at intersection point
1155 normS[1] = -TMath::Sin(php);
1156 normS[2] = 0;
1157 }
1158 else GetNormal(normS,fPoints->GetCov()+tID*6); // vector normal to hit module
1159 fElsDR[tID] = GetDRofELoss(t,cdip,fElsDR[tID],normS,ptot,etot);
1160 }
1161 //
1162 // negaive t-params: against the track direction for negative track, along for positive
1163 pcur = ptot;
1164 ecurr = etot;
1165 for (int ip=fFirstPosT;ip--;) {
1166 int tID = fElsId[ip];
1167 Double_t t = fCurT[ tID ];
1168 //
1169 if (tID>fPntLast) { // this is not a hit layer but passive layer
1170 double php = TMath::ATan2(yc-fParams[kR0]*TMath::Cos(fParams[kPhi0]+t),
1171 xc-fParams[kR0]*TMath::Cos(fParams[kPhi0]+t));
1172 normS[0] = -TMath::Cos(php); // normal to the cylinder at intersection point
1173 normS[1] = -TMath::Sin(php);
1174 normS[2] = 0;
1175 }
1176 else GetNormal(normS,fPoints->GetCov()+tID*6); // vector normal to hit module
1177 //
1178 fElsDR[tID] = GetDRofELoss(t,cdip,fElsDR[tID],normS,ptot,etot);
1179 }
1180 }
1181 // fill info needed to account for ELoss ------------------------------- <<<
1182 //
1183 return kTRUE;
1184}
1185
1186//____________________________________________________
1187Double_t AliITSTPArrayFit::FitHelix(Int_t extQ, Double_t extPT,Double_t extPTerr)
1188{
1189 // fit by helix accounting for the errors of all coordinates (and energy loss if requested)
1190 //
1191 // If extQ is non-0, its sign is imposed as a charge of the track
1192 // If extPT>0 and extPTerr>=0, constrain to measured tr.momentum PT
1193 // with corresponding error (err=0 -> rel.err=1e-6)
1194 //
1195 double chiprev=1e99;
1196 //const Double_t kMaxTEffect = 1E-6;
1197 Double_t dXYZdGlo[3*5],dXYZdLoc[3],xyzRes[3];
1198 //
1199 SetFitDone(kFALSE);
1200 fChi2NDF = -1;
1201 //
1202 if (!FitHelixCrude(extQ)) return -1; // get initial estimate, ignoring the errors
1203 //
1d06ac63 1204 if (TMath::Abs(fParams[kR0])>fMaxRforHelix && extPT<=0) {
1205 fSwitch2Line = kTRUE;
1206 return FitLine();
1207 }
1208 //
1209 //
6be22b3f 1210 if (!IsCovInv()) InvertPointsCovMat(); // prepare inverted errors
1211 if (!fParSol) fParSol = new AliParamSolver(5);
1212 fParSol->SetNGlobal(5);
1213 //
1214 // printf("-1 | %+.2e %+.2e %+.2e %+.2e %+.2e | chi2: %+.4e\n",fParams[0],fParams[1],fParams[2],fParams[3],fParams[4],CalcChi2NDF());
1215 int iter = 0;
1216 fChi2NDF = 1e99;
1217 Bool_t converged = kFALSE;
1218 while(iter<fMaxIter) {
1219 chiprev = fChi2NDF;
1220 fParSol->Clear();
1221 for (int ip=fPntFirst;ip<=fPntLast;ip++) {
1222 //
1223 GetResiduals(xyzRes, ip); // current residuals at point ip
1224 Double_t rrho = fParams[kR0]+fParams[kD0];
1225 Double_t cs0 = TMath::Cos(fParams[kPhi0]);
1226 Double_t sn0 = TMath::Sin(fParams[kPhi0]);
1227 Double_t cst = TMath::Cos(fCurT[ip]+fParams[kPhi0]);
1228 Double_t snt = TMath::Sin(fCurT[ip]+fParams[kPhi0]);
1229 //
1230 int offs = kD0; // dXYZ/dD0
1231 dXYZdGlo[offs + kX] = cs0;
1232 dXYZdGlo[offs + kY] = sn0;
1233 dXYZdGlo[offs + kZ] = 0;
1234 //
1235 offs = kPhi0*3; // dXYZ/dPhi0
1d06ac63 1236 dXYZdGlo[offs + kX] = -rrho*sn0 + fParams[kR0]*snt;
1237 dXYZdGlo[offs + kY] = rrho*cs0 - fParams[kR0]*cst;
6be22b3f 1238 dXYZdGlo[offs + kZ] = 0;
1239 //
1240 offs = kR0*3; // dXYZ/dR0
1241 dXYZdGlo[offs + kX] = cs0 - cst;
1242 dXYZdGlo[offs + kY] = sn0 - snt;
1243 dXYZdGlo[offs + kZ] = -fParams[kDip]*fCurT[ip];
1244 //
1245 offs = kDZ*3; // dXYZ/dDZ
1246 dXYZdGlo[offs + kX] = 0;
1247 dXYZdGlo[offs + kY] = 0;
1248 dXYZdGlo[offs + kZ] = 1.;
1249 //
1250 offs = kDip*3; // dXYZ/dDip
1251 dXYZdGlo[offs + kX] = 0;
1252 dXYZdGlo[offs + kY] = 0;
1253 dXYZdGlo[offs + kZ] = -fParams[kR0]*fCurT[ip];
1254 //
1255 dXYZdLoc[kX] = fParams[kR0]*snt;
1256 dXYZdLoc[kY] = -fParams[kR0]*cst;
1257 dXYZdLoc[kZ] = -fParams[kR0]*fParams[kDip];
1258 //
1259 fParSol->AddEquation(dXYZdGlo,dXYZdLoc,xyzRes,GetCovI(ip));
1260 }
1261 //
1262 if (extPT>0) { // add constraint on pt
1263 if (extPTerr<fgkAlmostZero) extPTerr = 1e-6*extPT;
1264 Double_t cf = fBz*GetCharge()*fgkCQConv;
1265 Double_t err2i = extPTerr/cf;
1266 err2i = 1./err2i/err2i;
1267 // printf("Constrain R to %+e\n",extPT/cf);
1268 fParSol->AddConstraint(kR0,-extPT/cf+fParams[kR0],err2i);
1269 }
1270 if (!fParSol->Solve()) { AliError("Failed to fit helix"); return -1; }
1271 Double_t *deltaG = fParSol->GetGlobals();
1272 Double_t *deltaT = fParSol->GetLocals();
1273 for (int ipar=5;ipar--;) fParams[ipar] -= deltaG[ipar];
1d06ac63 1274 for (int ip=fPntFirst;ip<=fPntLast;ip++) {
1275 fCurT[ip] = CalcParPCA(ip);
1276 // printf("iter%d : delta%2d : expl: %+e | %+e | R=%+e p0=%+e\n",iter,ip,deltaT[ip-fPntFirst], fCurT[ip],fParams[kR0],fParams[kPhi0]);
1277 // fCurT[ip] -= deltaT[ip-fPntFirst];
1278 }
6be22b3f 1279 iter++;
1280 //
1281 fChi2NDF = CalcChi2NDF();
1282 // printf("%d | %+.2e %+.2e %+.2e %+.2e %+.2e | chi2: %+.4e %+.4e\n",iter,deltaG[0],deltaG[1],deltaG[2],deltaG[3],deltaG[4],fChi2NDF,fChi2NDF-chiprev);
1283 // printf("->> %+.2e %+.2e %+.2e %+.2e %+.2e | Chi2: %+.6e %+.6e\n",fParams[0],fParams[1],fParams[2],fParams[3],fParams[4],fChi2NDF,fChi2NDF-chiprev);
1284 double difchi2 = chiprev - fChi2NDF;
1285 if ( difchi2<fEps && TMath::Abs(difchi2)<1e-4) {converged = kTRUE; break;}
1286 // if (errT*TMath::Abs(fParams[kR0])<kMaxTEffect && errP<fEps) {converged = kTRUE; break;}
1287 }
1288 //
1289 if (!converged) {
1290 AliDebug(2,Form("Max number of %d iteration reached, Current chi2:%.3e, chi2 change %+.3e",iter,
1291 fChi2NDF,chiprev-fChi2NDF));
1292 for (int ip=fPntFirst;ip<=fPntLast;ip++)
1293 AliDebug(2,Form("P%2d| %+.3e %+.3e %+.3e\n",ip,fPoints->GetX()[ip],fPoints->GetY()[ip],fPoints->GetZ()[ip]));
1294
1295 }
1296 fIter = iter;
1297 SetCharge( fParams[kR0]>0 ? (fBz<0?-1:1):(fBz>0?-1:1) );
1298 SetFitDone();
1299 // printf("F1>> %+.7e %+.7e %+.7e %+.7e %.7e\n",fParams[0],fParams[1],fParams[2],fParams[3],fParams[4]);
1300 //
1301 return fChi2NDF;
1302}
1303
1304//____________________________________________________
1305Double_t AliITSTPArrayFit::FitLine()
1306{
1307 // fit by helix accounting for the errors of all coordinates (and energy loss if requested)
1308 //
1309 double chiprev=1e99;
1310 // const Double_t kMaxTEffect = 1.e-6;
1311 Double_t dXYZdGlo[3*4],dXYZdLoc[3],xyzRes[3];
1312 SetFitDone(kFALSE);
1313 fChi2NDF = -1;
1314 //
1315 if (fParAxis<0) SetParAxis(ChoseParAxis());
1316 //
1317 const float *xyzp[3]={fPoints->GetX(),fPoints->GetY(),fPoints->GetZ()};
1318 if (!IsCovInv()) InvertPointsCovMat();
1319 if (!FitLineCrude()) return -1; // get initial estimate, ignoring the errors
1320 //
1321 if (!fParSol) fParSol = new AliParamSolver(5);
1322 fParSol->SetNGlobal(4);
1323 // initial set of parameters
1324 for (int ip=fPntFirst;ip<=fPntLast;ip++) fCurT[ip] = xyzp[fParAxis][ip]; // use measured param-coordinate
1325 //
1326 int iter = 0;
1327 Bool_t converged = kFALSE;
1328 fChi2NDF = 1e99;
1329 while(iter<fMaxIter) {
1330 chiprev = fChi2NDF;
1331 fParSol->Clear();
1332 for (int ip=fPntFirst;ip<=fPntLast;ip++) {
1333 //
1334 int offs;
1335 GetResiduals(xyzRes, ip); // current residuals at point ip
1336 //
1337 offs = kA0*3; // dXYZ/dA0
1338 dXYZdGlo[offs + fkAxID[kX]] = 1;
1339 dXYZdGlo[offs + fkAxID[kY]] = 0;
1340 dXYZdGlo[offs + fParAxis ] = 0;
1341 //
1342 offs = kB0*3; // dXYZ/dB0
1343 dXYZdGlo[offs + fkAxID[kX]] = fCurT[ip];
1344 dXYZdGlo[offs + fkAxID[kY]] = 0;
1345 dXYZdGlo[offs + fParAxis ] = 0;
1346 //
1347 offs = kA1*3; // dXYZ/dA1
1348 dXYZdGlo[offs + fkAxID[kX]] = 0;
1349 dXYZdGlo[offs + fkAxID[kY]] = 1;
1350 dXYZdGlo[offs + fParAxis ] = 0;
1351 //
1352 offs = kB1*3; // dXYZ/dB1
1353 dXYZdGlo[offs + fkAxID[kX]] = 0;
1354 dXYZdGlo[offs + fkAxID[kY]] = fCurT[ip];
1355 dXYZdGlo[offs + fParAxis ] = 0;
1356 //
1357 dXYZdLoc[ fkAxID[kX] ] = fParams[kB0]; // dX/dt
1358 dXYZdLoc[ fkAxID[kY] ] = fParams[kB1]; // dY/dt
1359 dXYZdLoc[ fParAxis ] = 1;
1360 //
1361 fParSol->AddEquation(dXYZdGlo,dXYZdLoc,xyzRes,GetCovI(ip));
1362 }
1363 //
1364 if (!fParSol->Solve()) { AliError("Failed to fit line"); return -1; }
1365 Double_t *deltaG = fParSol->GetGlobals();
1366 Double_t *deltaT = fParSol->GetLocals();
1367 for (int ipar=4;ipar--;) fParams[ipar] -= deltaG[ipar];
1368 for (int ip=fPntFirst;ip<=fPntLast;ip++) fCurT[ip] -= deltaT[ip-fPntFirst];
1369 iter++;
1370 fChi2NDF = CalcChi2NDF();
1371 // printf("%d %+e %+e | %+.2e %+.2e %+.2e %+.2e | chi2: %+.4e %+.4e\n",iter,errP,errT, deltaG[0],deltaG[1],deltaG[2],deltaG[3],fChi2NDF,fChi2NDF-chiprev);
1372 // printf("->> %+.2e %+.2e %+.2e %+.2e %+.2e | Chi2: %+.6e %+.6e\n",fParams[0],fParams[1],fParams[2],fParams[3],fParams[4],fChi2NDF,fChi2NDF-chiprev);
1373 double difchi2 = chiprev - fChi2NDF;
1374 if ( difchi2<fEps && TMath::Abs(difchi2)<1e-4) {converged = kTRUE; break;}
1375 chiprev = fChi2NDF;
1376 // if (errT<kMaxTEffect && errP<fEps) {converged = kTRUE; break;}
1377 }
1378 //
1379 if (!converged) {
1380 AliDebug(2,Form("Max number of %d iteration reached, Current chi2:%.3e, chi2 change %+.3e",iter,
1381 fChi2NDF,chiprev-fChi2NDF));
1382 for (int ip=fPntFirst;ip<=fPntLast;ip++)
1383 AliDebug(2,Form("P%2d| %+.3e %+.3e %+.3e\n",ip,fPoints->GetX()[ip],fPoints->GetY()[ip],fPoints->GetZ()[ip]));
1384 }
1385 fIter = iter;
1386 SetFitDone();
1387 //printf("F1>> %+.2e %+.2e %+.2e %+.2e\n",fParams[0],fParams[1],fParams[2],fParams[3]);
1388 return fChi2NDF;
1389 //
1390}
1391
1392//____________________________________________________
1393void AliITSTPArrayFit::GetNormal(Double_t *norm, const Float_t *covMat)
1394{
1395 // obtain the lab normal vector to the sensor from the covariance matrix
1396 // in such a way that when the local frame of the sensor coincides with
1397 // the lab frame, the vector {0,1,0} is obtained
1398 Double_t tgxy = TMath::Tan(0.5*TMath::ATan2(2.*covMat[kXY],covMat[kYY]-covMat[kXX]));
1399 Double_t tgyz = TMath::Tan(0.5*TMath::ATan2(2.*covMat[kYZ],covMat[kZZ]-covMat[kYY]));
1400 norm[kY] = 1./TMath::Sqrt(1 + tgxy*tgxy + tgyz*tgyz);
1401 norm[kX] = norm[kY]*tgxy;
1402 norm[kZ] = norm[kY]*tgyz;
1403 //
1404}
1405
1406//____________________________________________________
1407Double_t AliITSTPArrayFit::GetDRofELoss(Double_t t,Double_t cdip,Double_t rhoL,const Double_t *normS,
1408 Double_t &p,Double_t &e) const
1409{
1410 // Calculate energy loss of the particle at given t-param on the layer with rhoL (thickness*density) with
1411 // normal vector normS in the lab. The particle before eloss has energy "e" and momentum "p"
1412 // cdip = cosine of the dip angle = 1/sqrt(1+tgL^2)
1413 // Return the change DR of the radius due to the ELoss
1414 //
1415 // NOTE: with B>0 the negative particles propagate along increasing t-param and positive
1416 // particles - against.
1417 // t-param = 0 corresponds to the point of closest approach of the track to the beam.
1418 // Since the fitted helix parameters of the track are defined in this PCA point, when the correction
1419 // is applied upstream of the PCS, the energy must be increased (DR>0) rather than decreased (DR<0)
1420 //
1421 Double_t dirTr[3];
1422 dirTr[0] = -TMath::Sin(fParams[kPhi0]+t);
1423 dirTr[1] = TMath::Cos(fParams[kPhi0]+t);
1424 dirTr[2] = fParams[kDip];
1425 // cosine of the impact angle
1426 Double_t cosImp = cdip*TMath::Abs(dirTr[0]*normS[0]+dirTr[1]*normS[1]+dirTr[2]*normS[2]);
1427 //
1428 if (cosImp<0.3) cosImp = 0.3; //?
1429 Double_t dE = AliExternalTrackParam::BetheBlochSolid(p/fMass)*rhoL/cosImp;
1430 Double_t dP = e/p*dE;
1431 //
1432 if (t*GetSignQB() < 0) {
1433 dP = -dP;
1434 dE = -dE;
1435 }
1436 //
1437 if (p+dP<0) {
1438 AliInfo(Form("Estimated PLoss %.3f is larger than particle momentum %.3f. Skipping",dP,p));
1439 return 0;
1440 }
1441 //
1442 p += dP;
1443 e += dE;
1444 //
1445 return fCharge*dP*cdip/fBz/fgkCQConv;
1446}
1447
1448//_____________________________________________________________
1449Double_t AliITSTPArrayFit::GetLineOffset(Int_t axis) const
1450{
1451 // return intercept of the parameterization coord = intercept + slope*t for given axis
1452 if (fParAxis<0) return -1E6; // no line fit
1453 if (axis==fParAxis) return 0;
1454 if (fParAxis==kX) return fParams[axis==kY ? kA0 : kA1 ];
1455 if (fParAxis==kY) return fParams[axis==kZ ? kA0 : kA1 ];
1456 return fParams[axis==kX ? kA0 : kA1 ];
1457}
1458
1459//_____________________________________________________________
1460Double_t AliITSTPArrayFit::GetLineSlope(Int_t axis) const
1461{
1462 // return intercept of the parameterization coord = intercept + slope*t for given axis
1463 if (fParAxis<0) return -1E6; // no line fit
1464 if (axis==fParAxis) return 1.;
1465 if (fParAxis==kX) return fParams[axis==kY ? kB0 : kB1 ];
1466 if (fParAxis==kY) return fParams[axis==kZ ? kB0 : kB1 ];
1467 return fParams[axis==kX ? kB0 : kB1 ];
1468}
1469
1470//_____________________________________________________________
1471void AliITSTPArrayFit::Print(Option_t *) const
1472{
1473 const char kCxyz[] = "XYZ";
1474 if (!fPoints) return;
1475 //
1476 printf("Track of %3d points in Bz=%+.1f |Fit ",fPntLast-fPntFirst+1,fBz);
1477 if ( IsFitDone() ) {
1478 if (IsFieldON())
1479 printf("Helix: Chi2: %5.1f | %+.2e %+.2e %+.2e %+.2e %+.2e\n",
1480 fChi2NDF,fParams[kD0],fParams[kPhi0],fParams[kR0],fParams[kDZ],fParams[kDip]);
1481 else
1482 printf("Line%c: Chi2: %5.1f | %+.2e %+.2e %+.2e %+.2e\n",
1483 kCxyz[fParAxis],fChi2NDF,fParams[kA0],fParams[kB0],fParams[kA1],fParams[kB1]);
1484 }
1485 else printf("N/A\n");
1486}
1487
1488
1489
1490
1491//____________________________________________________
1492void AliITSTPArrayFit::BuildMaterialLUT(Int_t ntri)
1493{
1494 // Fill a look-up table with mean material a la AliITSTrackerMI
1495 //
1496 if (!AliGeomManager::GetGeometry()) AliFatal("Geometry is not loaded");
1497 //
1498 // detector layer to check: dX,dZ,Ymin,Ymax
1499 const double kLayr[9][4] = {{0. ,60. , 2.80,3.00}, // beam pipe
1500 {1.28,7.07,-0.20,0.22}, // SPD1
1501 {1.28,7.07,-0.20,0.22}, // SPD2
1502 {0. ,76.0, 10.4,11.8}, // Shield1
1503 {7.02,7.53,-1.00,4.50}, // SDD1
1504 {7.02,7.53,-1.00,4.50}, // SDD2
1505 {0. ,102., 29.0,30.0}, // Shield2
1506 {7.50,4.20,-0.15,4.50}, // SSD1
1507 {7.50,4.20,-0.15,4.50}}; // SSD2
1508 //
1509 //
1510 // build <dens*L> for detectors (track hitting the sensor in normal direction)
1511 double pg1[3],pg2[3],res[7];
1512 //
1513 int sID = 0;
1514 int actLrID = 0;
1515 for (int lr=0;lr<9;lr++) {
1516 //
1517 Bool_t active = kFALSE;
1518 const double* tpars = kLayr[lr];
1519 //
1520 if (IsZero(tpars[0])) { // passive layer
1521 active = kFALSE;
1522 AliInfo(Form("Probing passive layer (total layer #%d)",lr));
1523 }
1524 else {
1525 active = kTRUE;
1526 sID += AliGeomManager::LayerSize(++actLrID);
1527 AliInfo(Form("Probing sensors of active layer #%d (total layers #%d)",actLrID,lr));
1528 }
1529 double shift = TMath::Abs(tpars[2]-tpars[3])*1E-4;
1530 double rhol = 0;
1531 for (int i=ntri;i--;) {
1532 //
1533 if (active) {
1534 int ssID = sID -1 - AliGeomManager::LayerSize(actLrID)*gRandom->Rndm();
1535 pg1[0] = pg2[0] = (gRandom->Rndm()-0.5)*tpars[0] + shift; // local X
1536 pg2[0] -= 2*shift;
1537 pg1[1] = tpars[2];
1538 pg2[1] = tpars[3];
1539 pg1[2] = pg2[2] = (gRandom->Rndm()-0.5)*tpars[1] + shift; // local Z
1540 pg2[2] -= 2*shift;
1541 AliITSgeomTGeo::LocalToGlobal(ssID,pg1,pg1);
1542 AliITSgeomTGeo::LocalToGlobal(ssID,pg2,pg2);
1543 }
1544 else {
1545 double ang = gRandom->Rndm()*TMath::Pi()*2;
1546 pg1[0] = tpars[2]*TMath::Cos(ang)+shift;
1547 pg2[0] = tpars[3]*TMath::Cos(ang)-shift;
1548 pg1[1] = tpars[2]*TMath::Sin(ang);
1549 pg2[1] = tpars[3]*TMath::Sin(ang);
1550 pg1[2] = pg2[2] = (gRandom->Rndm()-0.5)*tpars[1]+shift; // local Z
1551 pg2[2] -= 2*shift;
1552 }
1553
1554 //
1555 AliTracker::MeanMaterialBudget(pg1,pg2,res);
1556 rhol += res[0]*res[4]; // rho*L
1557 }
1558 fgRhoLITS[lr] = rhol/ntri;
1559 AliInfo(Form("Obtained <rho*L> = %e\n",fgRhoLITS[lr]));
1560 }
1561 //
1562 return;
1563}
1564
6be22b3f 1565//____________________________________________________
1566Double_t AliITSTPArrayFit::GetPCA2PlaneInfo(Double_t *xyz, Double_t *dir, Int_t axis, Double_t axval) const
1567{
1568 // calculate the PCA to plane normal ti axis and crossing it at axval
1569 // fill the position and direction cosines at this point
1570 //
1571 double xyzp[3] = {0,0,0}; // create fake point
1572 xyzp[axis] = axval;
1573 double covI[6] = {1e-4,0,0,1e-4,0,1e-4}; // fake cov.matrix loose in all directions
1574 covI[4*axis - axis*(axis+1)/2] = 1e8; // except axis
1575 //
1576 double t = GetPosition(xyz, xyzp, covI); // got pca
1577 //
1578 if (dir) GetDirCos(dir,t);
1579 return t;
1580}
1581
66214d86 1582//____________________________________________________
1583void AliITSTPArrayFit::GetT0Info(Double_t* xyz, Double_t *dir) const
1584{
1585 // get direction cosines for t = 0;
1586 GetPosition(xyz, 0);
1587 if (dir) GetDirCos(dir,0);
1588}
1589
1590//____________________________________________________
1591Bool_t AliITSTPArrayFit::CalcErrorMatrix()
1592{
1593 // compute covariance matrix in lenear approximation of residuals on parameters
1594 static AliSymMatrix cv(5);
1595 static Double_t dres[5][3];
1596 cv.Reset();
1597 int npar = IsFieldON() ? 5:4;
1598 //
1599 for (int ip=fPntFirst;ip<=fPntLast;ip++) {
1600 GetDResDParams(&dres[0][0],ip);
1601 Double_t* covI = GetCovI(ip);
1602 for (int i=npar;i--;)
1603 for (int j=i+1;j--;)
1604 cv(i,j) += dres[i][kX]*(dres[j][kX]*covI[ kXX ] + dres[j][kY]*covI[ kXY ] + dres[j][kZ]*covI[ kXZ ])
1605 + dres[i][kY]*(dres[j][kX]*covI[ kXY ] + dres[j][kY]*covI[ kYY ] + dres[j][kZ]*covI[ kYZ ])
1606 + dres[i][kZ]*(dres[j][kX]*covI[ kXZ ] + dres[j][kY]*covI[ kYZ ] + dres[j][kZ]*covI[ kZZ ]);
1607 }
1608 cv.SetSizeUsed(npar);
1609 if (cv.InvertChol()) {
1610 cv.Print("l");
1611 int cnt = 0;
1612 for (int i=npar;i--;) for (int j=i+1;j--;)fParamsCov[cnt++] = cv(i,j);
1613 return kTRUE;
1614 }
1615 //
1616 return kFALSE;
1617}
1d06ac63 1618
1619//____________________________________________________
1620Double_t AliITSTPArrayFit::CalcParPCA(Int_t ipnt) const
1621{
1622 // get parameter for the point with least weighted distance to the point
1623 const double *xyz = GetPoint(ipnt);
1624 const double *covI = GetCovI(ipnt);
1625 if (IsFieldON()) return GetParPCAHelix(xyz,covI);
1626 else return GetParPCALine(xyz,covI);
1627}