]> git.uio.no Git - u/mrichter/AliRoot.git/blame - TPC/TPCbase/AliTPCCorrection.cxx
doxy: TPC/TPCbase converted
[u/mrichter/AliRoot.git] / TPC / TPCbase / AliTPCCorrection.cxx
CommitLineData
0116859c 1/**************************************************************************
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 **************************************************************************/
15
7d855b04 16/// \class AliTPCCorrection
17/// \brief <h2> AliTPCCorrection class </h2>
18///
19/// The AliTPCCorrection class provides a general framework to deal with space point distortions.
20/// An correction class which inherits from here is for example AliTPCExBBShape or AliTPCExBTwist.
21/// General virtual functions are (for example) CorrectPoint(x,roc) where x is the vector of initial
22/// positions in cartesian coordinates and roc represents the read-out chamber number according to
23/// the offline numbering convention. The vector x is overwritten with the corrected coordinates.
24/// An alternative usage would be CorrectPoint(x,roc,dx), which leaves the vector x untouched, but
25/// returns the distortions via the vector dx.
26/// This class is normally used via the general class AliTPCComposedCorrection.
27///
28/// Furthermore, the class contains basic geometrical descriptions like field cage radii
29/// (fgkIFCRadius, fgkOFCRadius) and length (fgkTPCZ0) plus the voltages. Also, the definitions
30/// of size and widths of the fulcrums building the grid of the final look-up table, which is
31/// then interpolated, is defined in kNX and fgkXList).
32///
33/// All physics-model classes below are derived from this class in order to not duplicate code
34/// and to allow a uniform treatment of all physics models.
35///
36/// <h3> Poisson solver </h3>
37/// A numerical solver of the Poisson equation (relaxation technique) is implemented for 2-dimensional
38/// geometries (r,z) as well as for 3-dimensional problems (r,$\phi$,z). The corresponding function
39/// names are PoissonRelaxation?D. The relevant function arguments are the arrays of the boundary and
40/// initial conditions (ArrayofArrayV, ArrayofChargeDensities) as well as the grid granularity which
41/// is used during the calculation. These inputs can be chosen according to the needs of the physical
42/// effect which is supposed to be simulated. In the 3D version, different symmetry conditions can be set
43/// in order to reduce the calculation time (used in AliTPCFCVoltError3D).
44///
45/// <h3> Unified plotting functionality </h3>
46/// Generic plot functions were implemented. They return a histogram pointer in the chosen plane of
47/// the TPC drift volume with a selectable grid granularity and the magnitude of the correction vector.
48/// For example, the function CreateHistoDZinXY(z,nx,ny) returns a 2-dimensional histogram which contains
49/// the longitudinal corrections $dz$ in the (x,y)-plane at the given z position with the granularity of
50/// nx and ny. The magnitude of the corrections is defined by the class from which this function is called.
51/// In the same manner, standard plots for the (r,$\phi$)-plane and for the other corrections like $dr$ and $rd\phi$ are available
52///
53/// Note: This class is normally used via the class AliTPCComposedCorrection
54/// ![Picture from ROOT macro](AliTPCCorrection_cxx_e4df765.png)
55///
56/// \author Magnus Mager, Stefan Rossegger, Jim Thomas
57/// \date 27/04/2010
b4caed64 58
59
be67055b 60#include "Riostream.h"
0116859c 61
62#include <TH2F.h>
63#include <TMath.h>
64#include <TROOT.h>
cf5b0aa0 65#include <TTreeStream.h>
ffab0c37 66#include <TTree.h>
67#include <TFile.h>
e527a1b9 68#include <TTimeStamp.h>
ffab0c37 69#include <AliCDBStorage.h>
70#include <AliCDBId.h>
71#include <AliCDBMetaData.h>
c9cbd2f2 72#include "TVectorD.h"
73#include "AliTPCParamSR.h"
7f4cb119 74
c9cbd2f2 75#include "AliTPCCorrection.h"
76#include "AliLog.h"
1b923461 77
1b923461 78#include "AliExternalTrackParam.h"
79#include "AliTrackPointArray.h"
80#include "TDatabasePDG.h"
81#include "AliTrackerBase.h"
82#include "AliTPCROC.h"
83#include "THnSparse.h"
84
c9cbd2f2 85#include "AliTPCLaserTrack.h"
86#include "AliESDVertex.h"
87#include "AliVertexerTracks.h"
88#include "TDatabasePDG.h"
89#include "TF1.h"
7f4cb119 90#include "TRandom.h"
c9cbd2f2 91
92#include "TDatabasePDG.h"
93
7f4cb119 94#include "AliTPCTransform.h"
95#include "AliTPCcalibDB.h"
96#include "AliTPCExB.h"
cf5b0aa0 97
f2bce741 98//#include "AliTPCRecoParam.h"
fdbbc146 99#include "TLinearFitter.h"
d9ef0909 100#include <AliSysInfo.h>
0116859c 101
7d855b04 102/// \cond CLASSIMP
cf5b0aa0 103ClassImp(AliTPCCorrection)
7d855b04 104/// \endcond
105
cf5b0aa0 106
f1817479 107TObjArray *AliTPCCorrection::fgVisualCorrection=0;
108// instance of correction for visualization
109
110
0116859c 111// FIXME: the following values should come from the database
7d855b04 112const Double_t AliTPCCorrection::fgkTPCZ0 = 249.7; ///< nominal gating grid position
113const Double_t AliTPCCorrection::fgkIFCRadius= 83.5; ///< radius which renders the "18 rod manifold" best -> compare calc. of Jim Thomas
2b68ab9c 114// compare gkIFCRadius= 83.05: Mean Radius of the Inner Field Cage ( 82.43 min, 83.70 max) (cm)
7d855b04 115const Double_t AliTPCCorrection::fgkOFCRadius= 254.5; ///< Mean Radius of the Outer Field Cage (252.55 min, 256.45 max) (cm)
116const Double_t AliTPCCorrection::fgkZOffSet = 0.2; ///< Offset from CE: calculate all distortions closer to CE as if at this point
117const Double_t AliTPCCorrection::fgkCathodeV = -100000.0; ///< Cathode Voltage (volts)
118const Double_t AliTPCCorrection::fgkGG = -70.0; ///< Gating Grid voltage (volts)
119
120const Double_t AliTPCCorrection::fgkdvdE = 0.0024; ///< [cm/V] drift velocity dependency on the E field (from Magboltz for NeCO2N2 at standard environment)
0116859c 121
7d855b04 122const Double_t AliTPCCorrection::fgkEM = -1.602176487e-19/9.10938215e-31; ///< charge/mass in [C/kg]
123const Double_t AliTPCCorrection::fgke0 = 8.854187817e-12; ///< vacuum permittivity [A·s/(V·m)]
0116859c 124
0116859c 125
7d855b04 126AliTPCCorrection::AliTPCCorrection()
d9ef0909 127 : TNamed("correction_unity","unity"),fILow(0),fJLow(0),fKLow(0), fT1(1), fT2(1), fIsLocal(kFALSE)
0116859c 128{
7d855b04 129 /// default constructor
130
f1817479 131 if (!fgVisualCorrection) fgVisualCorrection= new TObjArray;
c9cbd2f2 132
35ae345f 133 InitLookUpfulcrums();
c9cbd2f2 134
0116859c 135}
136
137AliTPCCorrection::AliTPCCorrection(const char *name,const char *title)
d9ef0909 138 : TNamed(name,title),fILow(0),fJLow(0),fKLow(0), fT1(1), fT2(1), fIsLocal(kFALSE)
0116859c 139{
7d855b04 140 /// default constructor, that set the name and title
141
f1817479 142 if (!fgVisualCorrection) fgVisualCorrection= new TObjArray;
c9cbd2f2 143
35ae345f 144 InitLookUpfulcrums();
c9cbd2f2 145
0116859c 146}
147
148AliTPCCorrection::~AliTPCCorrection() {
7d855b04 149 /// virtual destructor
150
0116859c 151}
152
69d03c4d 153Bool_t AliTPCCorrection::AddCorrectionCompact(AliTPCCorrection* corr, Double_t weight){
7d855b04 154 /// Add correction and make them compact
155 /// Assumptions:
156 /// - origin of distortion/correction are additive
157 /// - only correction ot the same type supported ()
158
69d03c4d 159 if (corr==NULL) {
160 AliError("Zerro pointer - correction");
161 return kFALSE;
7d855b04 162 }
69d03c4d 163 AliError(TString::Format("Correction %s not implementend",IsA()->GetName()).Data());
164 return kFALSE;
165}
166
167
5a516e0a 168void AliTPCCorrection::CorrectPoint(Float_t x[], Short_t roc) {
7d855b04 169 /// Corrects the initial coordinates x (cartesian coordinates)
170 /// according to the given effect (inherited classes)
171 /// roc represents the TPC read out chamber (offline numbering convention)
172
0116859c 173 Float_t dx[3];
174 GetCorrection(x,roc,dx);
175 for (Int_t j=0;j<3;++j) x[j]+=dx[j];
176}
177
5a516e0a 178void AliTPCCorrection::CorrectPoint(const Float_t x[], Short_t roc,Float_t xp[]) {
7d855b04 179 /// Corrects the initial coordinates x (cartesian coordinates) and stores the new
180 /// (distorted) coordinates in xp. The distortion is set according to the given effect (inherited classes)
181 /// roc represents the TPC read out chamber (offline numbering convention)
182
0116859c 183 Float_t dx[3];
184 GetCorrection(x,roc,dx);
185 for (Int_t j=0;j<3;++j) xp[j]=x[j]+dx[j];
186}
187
5a516e0a 188void AliTPCCorrection::DistortPoint(Float_t x[], Short_t roc) {
7d855b04 189 /// Distorts the initial coordinates x (cartesian coordinates)
190 /// according to the given effect (inherited classes)
191 /// roc represents the TPC read out chamber (offline numbering convention)
192
0116859c 193 Float_t dx[3];
194 GetDistortion(x,roc,dx);
195 for (Int_t j=0;j<3;++j) x[j]+=dx[j];
196}
197
5a516e0a 198void AliTPCCorrection::DistortPointLocal(Float_t x[], Short_t roc) {
7d855b04 199 /// Distorts the initial coordinates x (cartesian coordinates)
200 /// according to the given effect (inherited classes)
201 /// roc represents the TPC read out chamber (offline numbering convention)
202
46e89793 203 Float_t gxyz[3]={0,0,0};
a5fca02f 204 Double_t alpha = TMath::TwoPi()*(roc%18+0.5)/18;
46e89793 205 Double_t ca=TMath::Cos(alpha), sa= TMath::Sin(alpha);
206 gxyz[0]= ca*x[0]+sa*x[1];
207 gxyz[1]= -sa*x[0]+ca*x[1];
208 gxyz[2]= x[2];
209 DistortPoint(gxyz,roc);
210 x[0]= ca*gxyz[0]-sa*gxyz[1];
211 x[1]= +sa*gxyz[0]+ca*gxyz[1];
212 x[2]= gxyz[2];
213}
5a516e0a 214void AliTPCCorrection::CorrectPointLocal(Float_t x[], Short_t roc) {
7d855b04 215 /// Distorts the initial coordinates x (cartesian coordinates)
216 /// according to the given effect (inherited classes)
217 /// roc represents the TPC read out chamber (offline numbering convention)
218
46e89793 219 Float_t gxyz[3]={0,0,0};
a5fca02f 220 Double_t alpha = TMath::TwoPi()*(roc%18+0.5)/18;
46e89793 221 Double_t ca=TMath::Cos(alpha), sa= TMath::Sin(alpha);
222 gxyz[0]= ca*x[0]+sa*x[1];
223 gxyz[1]= -sa*x[0]+ca*x[1];
224 gxyz[2]= x[2];
225 CorrectPoint(gxyz,roc);
226 x[0]= ca*gxyz[0]-sa*gxyz[1];
227 x[1]= sa*gxyz[0]+ca*gxyz[1];
228 x[2]= gxyz[2];
229}
230
5a516e0a 231void AliTPCCorrection::DistortPoint(const Float_t x[], Short_t roc,Float_t xp[]) {
7d855b04 232 /// Distorts the initial coordinates x (cartesian coordinates) and stores the new
233 /// (distorted) coordinates in xp. The distortion is set according to the given effect (inherited classes)
234 /// roc represents the TPC read out chamber (offline numbering convention)
235
0116859c 236 Float_t dx[3];
237 GetDistortion(x,roc,dx);
238 for (Int_t j=0;j<3;++j) xp[j]=x[j]+dx[j];
239}
240
5a516e0a 241void AliTPCCorrection::GetCorrection(const Float_t /*x*/[], Short_t /*roc*/,Float_t dx[]) {
7d855b04 242 /// This function delivers the correction values dx in respect to the inital coordinates x
243 /// roc represents the TPC read out chamber (offline numbering convention)
244 /// Note: The dx is overwritten by the inherited effectice class ...
245
0116859c 246 for (Int_t j=0;j<3;++j) { dx[j]=0.; }
247}
248
5a516e0a 249void AliTPCCorrection::GetDistortion(const Float_t x[], Short_t roc,Float_t dx[]) {
7d855b04 250 /// This function delivers the distortion values dx in respect to the inital coordinates x
251 /// roc represents the TPC read out chamber (offline numbering convention)
252
0116859c 253 GetCorrection(x,roc,dx);
254 for (Int_t j=0;j<3;++j) dx[j]=-dx[j];
255}
256
5a516e0a 257void AliTPCCorrection::GetCorrectionDz(const Float_t x[], Short_t roc,Float_t dx[], Float_t delta) {
7d855b04 258 /// author: marian.ivanov@cern.ch
259 ///
260 /// In this (virtual)function calculates the dx'/dz, dy'/dz and dz'/dz at given point (x,y,z)
261 /// Generic implementation. Better precision can be acchieved knowing the internal structure
262 /// of underlying trasnformation. Derived classes can reimplement it.
263 /// To calculate correction is fitted in small neighberhood:
264 /// (x+-delta,y+-delta,z+-delta) where delta is an argument
265 ///
266 /// Input parameters:
267 /// x[] - space point corrdinate
268 /// roc - readout chamber identifier (important e.g to do not miss the side of detector)
269 /// delta - define the size of neighberhood
270 /// Output parameter:
271 /// dx[] - array {dx'/dz, dy'/dz , dz'/dz }
fdbbc146 272
d9ef0909 273 // if (fIsLocal){ //standard implemenation provides the correction/distortion integrated over full drift length
d9ef0909 274 //
7d855b04 275 //
276 // GetCorrection(xyz,roc,dxyz);
d9ef0909 277 // }
7d855b04 278 static TLinearFitter fitx(2,"pol1");
fdbbc146 279 static TLinearFitter fity(2,"pol1");
280 static TLinearFitter fitz(2,"pol1");
281 fitx.ClearPoints();
282 fity.ClearPoints();
283 fitz.ClearPoints();
2d4e971f 284 Int_t zmin=-2;
285 Int_t zmax=0;
7a8a504f 286 //adjust limits around CE to stay on one side
287 if ((roc%36)<18) {
288 //A-Side
289 if ((x[2]+zmin*delta)<0){
290 zmin=0;
291 zmax=2;
292 if ((x[2]-delta)>0){
293 zmin=-1;
294 zmax=1;
295 }
296 }
297 } else {
298 //C-Side
2d4e971f 299 zmin=0;
300 zmax=2;
7a8a504f 301 if ((x[2]+zmax*delta)>0){
302 zmin=-2;
303 zmax=0;
304 if ((x[2]+delta)<0){
305 zmin=-1;
306 zmax=1;
307 }
308 }
2d4e971f 309 }
7a8a504f 310
fdbbc146 311 for (Int_t xdelta=-1; xdelta<=1; xdelta++)
312 for (Int_t ydelta=-1; ydelta<=1; ydelta++){
2d4e971f 313// for (Int_t zdelta=-1; zdelta<=1; zdelta++){
314// for (Int_t xdelta=-2; xdelta<=0; xdelta++)
315// for (Int_t ydelta=-2; ydelta<=0; ydelta++){
316 for (Int_t zdelta=zmin; zdelta<=zmax; zdelta++){
317 //TODO: what happens if x[2] is on the A-Side, but x[2]+zdelta*delta
318 // will be on the C-Side?
fdbbc146 319 Float_t xyz[3]={x[0]+xdelta*delta, x[1]+ydelta*delta, x[2]+zdelta*delta};
320 Float_t dxyz[3];
321 GetCorrection(xyz,roc,dxyz);
322 Double_t adelta=zdelta*delta;
323 fitx.AddPoint(&adelta, dxyz[0]);
324 fity.AddPoint(&adelta, dxyz[1]);
325 fitz.AddPoint(&adelta, dxyz[2]);
326 }
327 }
328 fitx.Eval();
329 fity.Eval();
330 fitz.Eval();
331 dx[0] = fitx.GetParameter(1);
332 dx[1] = fity.GetParameter(1);
333 dx[2] = fitz.GetParameter(1);
334}
335
5a516e0a 336void AliTPCCorrection::GetDistortionDz(const Float_t x[], Short_t roc,Float_t dx[], Float_t delta) {
7d855b04 337 /// author: marian.ivanov@cern.ch
338 ///
339 /// In this (virtual)function calculates the dx'/dz, dy'/dz and dz'/dz at given point (x,y,z)
340 /// Generic implementation. Better precision can be acchieved knowing the internal structure
341 /// of underlying trasnformation. Derived classes can reimplement it.
342 /// To calculate distortion is fitted in small neighberhood:
343 /// (x+-delta,y+-delta,z+-delta) where delta is an argument
344 ///
345 /// Input parameters:
346 /// x[] - space point corrdinate
347 /// roc - readout chamber identifier (important e.g to do not miss the side of detector)
348 /// delta - define the size of neighberhood
349 /// Output parameter:
350 /// dx[] - array {dx'/dz, dy'/dz , dz'/dz }
351
2d4e971f 352 static TLinearFitter fitx(2,"pol1");
353 static TLinearFitter fity(2,"pol1");
354 static TLinearFitter fitz(2,"pol1");
355 fitx.ClearPoints();
356 fity.ClearPoints();
357 fitz.ClearPoints();
7a8a504f 358
359 Int_t zmin=-1;
360 Int_t zmax=1;
361 //adjust limits around CE to stay on one side
362 if ((roc%36)<18) {
363 //A-Side
364 if ((x[2]+zmin*delta)<0){
365 zmin=0;
366 zmax=2;
367 }
368 } else {
369 //C-Side
370 if ((x[2]+zmax*delta)>0){
371 zmin=-2;
372 zmax=0;
373 }
374 }
7d855b04 375
2d4e971f 376 //TODO: in principle one shuld check that x[2]+zdelta*delta does not get 'out of' bounds,
377 // so close to the CE it doesn't change the sign, since then the corrections will be wrong ...
378 for (Int_t xdelta=-1; xdelta<=1; xdelta++)
379 for (Int_t ydelta=-1; ydelta<=1; ydelta++){
7a8a504f 380 for (Int_t zdelta=zmin; zdelta<=zmax; zdelta++){
2d4e971f 381 //TODO: what happens if x[2] is on the A-Side, but x[2]+zdelta*delta
382 // will be on the C-Side?
383 //TODO: For the C-Side, does this have the correct sign?
384 Float_t xyz[3]={x[0]+xdelta*delta, x[1]+ydelta*delta, x[2]+zdelta*delta};
385 Float_t dxyz[3];
386 GetDistortion(xyz,roc,dxyz);
387 Double_t adelta=zdelta*delta;
388 fitx.AddPoint(&adelta, dxyz[0]);
389 fity.AddPoint(&adelta, dxyz[1]);
390 fitz.AddPoint(&adelta, dxyz[2]);
391 }
392 }
393 fitx.Eval();
394 fity.Eval();
395 fitz.Eval();
396 dx[0] = fitx.GetParameter(1);
397 dx[1] = fity.GetParameter(1);
398 dx[2] = fitz.GetParameter(1);
399}
400
5a516e0a 401void AliTPCCorrection::GetCorrectionIntegralDz(const Float_t x[], Short_t roc,Float_t dx[], Float_t delta){
7d855b04 402 /// Integrate 3D distortion along drift lines starting from the roc plane
403 /// to the expected z position of the point, this assumes that dz is small
404 /// and the error propagating to z' instead of the correct z is negligible
405 /// To define the drift lines virtual function AliTPCCorrection::GetCorrectionDz is used
406 ///
407 /// Input parameters:
408 /// x[] - space point corrdinate
409 /// roc - readout chamber identifier (important e.g to do not miss the side of detector)
410 /// delta - define the size of neighberhood
411 /// Output parameter:
412 /// dx[] - array { integral(dx'/dz), integral(dy'/dz) , integral(dz'/dz) }
fdbbc146 413
414 Float_t zroc= ((roc%36)<18) ? fgkTPCZ0:-fgkTPCZ0;
415 Double_t zdrift = TMath::Abs(x[2]-zroc);
416 Int_t nsteps = Int_t(zdrift/delta)+1;
417 //
418 //
2d4e971f 419 Float_t xyz[3]={x[0],x[1],zroc};
fdbbc146 420 Float_t dxyz[3]={x[0],x[1],x[2]};
2d4e971f 421 Short_t side=(roc/18)%2;
422 Float_t sign=1-2*side;
fdbbc146 423 Double_t sumdz=0;
424 for (Int_t i=0;i<nsteps; i++){
2d4e971f 425 //propagate backwards, therefore opposite signs
426 Float_t deltaZ=delta*(-sign);
427// if (xyz[2]+deltaZ>fgkTPCZ0) deltaZ=TMath::Abs(xyz[2]-fgkTPCZ0);
428// if (xyz[2]-deltaZ<-fgkTPCZ0) deltaZ=TMath::Abs(xyz[2]-fgkTPCZ0);
429 // protect again integrating through the CE
430 if (side==0){
431 if (xyz[2]+deltaZ<0) deltaZ=-xyz[2]+1e-20;
432 } else {
433 if (xyz[2]+deltaZ>0) deltaZ=xyz[2]-+1e-20;
434 }
435 // since at larger drift (smaller z) the corrections are larger (absolute, but negative)
436 // the slopes will be positive.
437 // but since we chose deltaZ opposite sign the singn of the corretion should be fine
7d855b04 438
2942f542 439 Float_t xyz2[3]={xyz[0],xyz[1],static_cast<Float_t>(xyz[2]+deltaZ/2.)};
12c02f0f 440 GetCorrectionDz(xyz2,roc,dxyz,delta/2.);
2d4e971f 441 xyz[0]+=deltaZ*dxyz[0];
fdbbc146 442 xyz[1]+=deltaZ*dxyz[1];
443 xyz[2]+=deltaZ; //
444 sumdz+=deltaZ*dxyz[2];
445 }
446 //
2d4e971f 447 dx[0]=xyz[0]-x[0];
448 dx[1]=xyz[1]-x[1];
449 dx[2]= sumdz; //TODO: is sumdz correct?
fdbbc146 450}
451
5a516e0a 452void AliTPCCorrection::GetDistortionIntegralDz(const Float_t x[], Short_t roc,Float_t dx[], Float_t delta){
7d855b04 453 /// Integrate 3D distortion along drift lines
454 /// To define the drift lines virtual function AliTPCCorrection::GetCorrectionDz is used
455 ///
456 /// Input parameters:
457 /// x[] - space point corrdinate
458 /// roc - readout chamber identifier (important e.g to do not miss the side of detector)
459 /// delta - define the size of neighberhood
460 /// Output parameter:
461 /// dx[] - array { integral(dx'/dz), integral(dy'/dz) , integral(dz'/dz) }
462
05da1b4e 463 Float_t zroc= ((roc%36)<18) ? fgkTPCZ0:-fgkTPCZ0;
464 Double_t zdrift = TMath::Abs(x[2]-zroc);
465 Int_t nsteps = Int_t(zdrift/delta)+1;
466 //
467 //
468 Float_t xyz[3]={x[0],x[1],x[2]};
469 Float_t dxyz[3]={x[0],x[1],x[2]};
470 Float_t sign=((roc%36)<18) ? 1.:-1.;
471 Double_t sumdz=0;
472 for (Int_t i=0;i<nsteps; i++){
473 Float_t deltaZ=delta;
2d4e971f 474 if (xyz[2]+deltaZ>fgkTPCZ0) deltaZ=TMath::Abs(xyz[2]-zroc);
475 if (xyz[2]-deltaZ<-fgkTPCZ0) deltaZ=TMath::Abs(xyz[2]-zroc);
476 // since at larger drift (smaller z) the distortions are larger
477 // the slopes will be negative.
478 // and since we are moving towards the read-out plane the deltaZ for
479 // weighting the dK/dz should have the opposite sign
05da1b4e 480 deltaZ*=sign;
2942f542 481 Float_t xyz2[3]={xyz[0],xyz[1],static_cast<Float_t>(xyz[2]+deltaZ/2.)};
12c02f0f 482 GetDistortionDz(xyz2,roc,dxyz,delta/2.);
2d4e971f 483 xyz[0]+=-deltaZ*dxyz[0];
484 xyz[1]+=-deltaZ*dxyz[1];
485 xyz[2]+=deltaZ; //TODO: Should this also be corrected for the dxyz[2]
486 sumdz+=-deltaZ*dxyz[2];
05da1b4e 487 }
488 //
2d4e971f 489 dx[0]=xyz[0]-x[0];
490 dx[1]=xyz[1]-x[1];
491 dx[2]= sumdz; //TODO: is sumdz correct?
7d855b04 492
05da1b4e 493}
fdbbc146 494
495
0116859c 496void AliTPCCorrection::Init() {
7d855b04 497 /// Initialization funtion (not used at the moment)
498
0116859c 499}
500
e527a1b9 501void AliTPCCorrection::Update(const TTimeStamp &/*timeStamp*/) {
7d855b04 502 /// Update function
503
e527a1b9 504}
505
0116859c 506void AliTPCCorrection::Print(Option_t* /*option*/) const {
7d855b04 507 /// Print function to check which correction classes are used
508 /// option=="d" prints details regarding the setted magnitude
509 /// option=="a" prints the C0 and C1 coefficents for calibration purposes
510
0116859c 511 printf("TPC spacepoint correction: \"%s\"\n",GetTitle());
512}
513
534fd34a 514void AliTPCCorrection:: SetOmegaTauT1T2(Float_t /*omegaTau*/,Float_t t1,Float_t t2) {
7d855b04 515 /// Virtual funtion to pass the wt values (might become event dependent) to the inherited classes
516 /// t1 and t2 represent the "effective omegaTau" corrections and were measured in a dedicated
517 /// calibration run
518
534fd34a 519 fT1=t1;
520 fT2=t2;
521 //SetOmegaTauT1T2(omegaTau, t1, t2);
0116859c 522}
523
524TH2F* AliTPCCorrection::CreateHistoDRinXY(Float_t z,Int_t nx,Int_t ny) {
7d855b04 525 /// Simple plot functionality.
526 /// Returns a 2d hisogram which represents the corrections in radial direction (dr)
527 /// in respect to position z within the XY plane.
528 /// The histogramm has nx times ny entries.
529
c9cbd2f2 530 AliTPCParam* tpcparam = new AliTPCParamSR;
531
4e8fafa8 532 TH2F *h=CreateTH2F("dr_xy", TString::Format("%s: DRinXY Z=%2.0f", GetTitle(),z).Data(),"x [cm]","y [cm]","dr [cm]",
0116859c 533 nx,-250.,250.,ny,-250.,250.);
534 Float_t x[3],dx[3];
535 x[2]=z;
536 Int_t roc=z>0.?0:18; // FIXME
537 for (Int_t iy=1;iy<=ny;++iy) {
538 x[1]=h->GetYaxis()->GetBinCenter(iy);
539 for (Int_t ix=1;ix<=nx;++ix) {
540 x[0]=h->GetXaxis()->GetBinCenter(ix);
541 GetCorrection(x,roc,dx);
542 Float_t r0=TMath::Sqrt((x[0] )*(x[0] )+(x[1] )*(x[1] ));
c9cbd2f2 543 if (tpcparam->GetPadRowRadii(0,0)<=r0 && r0<=tpcparam->GetPadRowRadii(36,95)) {
0116859c 544 Float_t r1=TMath::Sqrt((x[0]+dx[0])*(x[0]+dx[0])+(x[1]+dx[1])*(x[1]+dx[1]));
545 h->SetBinContent(ix,iy,r1-r0);
546 }
547 else
548 h->SetBinContent(ix,iy,0.);
549 }
550 }
c9cbd2f2 551 delete tpcparam;
0116859c 552 return h;
553}
554
555TH2F* AliTPCCorrection::CreateHistoDRPhiinXY(Float_t z,Int_t nx,Int_t ny) {
7d855b04 556 /// Simple plot functionality.
557 /// Returns a 2d hisogram which represents the corrections in rphi direction (drphi)
558 /// in respect to position z within the XY plane.
559 /// The histogramm has nx times ny entries.
0116859c 560
c9cbd2f2 561 AliTPCParam* tpcparam = new AliTPCParamSR;
562
4e8fafa8 563 TH2F *h=CreateTH2F("drphi_xy",TString::Format("%s: DRPhiinXY Z=%2.0f", GetTitle(),z).Data(),"x [cm]","y [cm]","drphi [cm]",
0116859c 564 nx,-250.,250.,ny,-250.,250.);
565 Float_t x[3],dx[3];
566 x[2]=z;
567 Int_t roc=z>0.?0:18; // FIXME
568 for (Int_t iy=1;iy<=ny;++iy) {
569 x[1]=h->GetYaxis()->GetBinCenter(iy);
570 for (Int_t ix=1;ix<=nx;++ix) {
571 x[0]=h->GetXaxis()->GetBinCenter(ix);
572 GetCorrection(x,roc,dx);
573 Float_t r0=TMath::Sqrt((x[0] )*(x[0] )+(x[1] )*(x[1] ));
c9cbd2f2 574 if (tpcparam->GetPadRowRadii(0,0)<=r0 && r0<=tpcparam->GetPadRowRadii(36,95)) {
0116859c 575 Float_t phi0=TMath::ATan2(x[1] ,x[0] );
576 Float_t phi1=TMath::ATan2(x[1]+dx[1],x[0]+dx[0]);
577
578 Float_t dphi=phi1-phi0;
579 if (dphi<TMath::Pi()) dphi+=TMath::TwoPi();
580 if (dphi>TMath::Pi()) dphi-=TMath::TwoPi();
7d855b04 581
0116859c 582 h->SetBinContent(ix,iy,r0*dphi);
583 }
584 else
585 h->SetBinContent(ix,iy,0.);
586 }
587 }
c9cbd2f2 588 delete tpcparam;
589 return h;
590}
591
592TH2F* AliTPCCorrection::CreateHistoDZinXY(Float_t z,Int_t nx,Int_t ny) {
7d855b04 593 /// Simple plot functionality.
594 /// Returns a 2d hisogram which represents the corrections in longitudinal direction (dz)
595 /// in respect to position z within the XY plane.
596 /// The histogramm has nx times ny entries.
c9cbd2f2 597
598 AliTPCParam* tpcparam = new AliTPCParamSR;
7d855b04 599
4e8fafa8 600 TH2F *h=CreateTH2F("dz_xy",TString::Format("%s: DZinXY Z=%2.0f", GetTitle(),z).Data(),"x [cm]","y [cm]","dz [cm]",
c9cbd2f2 601 nx,-250.,250.,ny,-250.,250.);
602 Float_t x[3],dx[3];
603 x[2]=z;
604 Int_t roc=z>0.?0:18; // FIXME
605 for (Int_t iy=1;iy<=ny;++iy) {
606 x[1]=h->GetYaxis()->GetBinCenter(iy);
607 for (Int_t ix=1;ix<=nx;++ix) {
608 x[0]=h->GetXaxis()->GetBinCenter(ix);
609 GetCorrection(x,roc,dx);
610 Float_t r0=TMath::Sqrt((x[0] )*(x[0] )+(x[1] )*(x[1] ));
611 if (tpcparam->GetPadRowRadii(0,0)<=r0 && r0<=tpcparam->GetPadRowRadii(36,95)) {
612 h->SetBinContent(ix,iy,dx[2]);
613 }
614 else
615 h->SetBinContent(ix,iy,0.);
616 }
617 }
618 delete tpcparam;
0116859c 619 return h;
620}
621
622TH2F* AliTPCCorrection::CreateHistoDRinZR(Float_t phi,Int_t nz,Int_t nr) {
7d855b04 623 /// Simple plot functionality.
624 /// Returns a 2d hisogram which represents the corrections in r direction (dr)
625 /// in respect to angle phi within the ZR plane.
626 /// The histogramm has nx times ny entries.
627
4e8fafa8 628 TH2F *h=CreateTH2F("dr_zr",TString::Format("%s: DRinZR Phi=%2.2f", GetTitle(),phi).Data(),"z [cm]","r [cm]","dr [cm]",
0116859c 629 nz,-250.,250.,nr,85.,250.);
630 Float_t x[3],dx[3];
631 for (Int_t ir=1;ir<=nr;++ir) {
632 Float_t radius=h->GetYaxis()->GetBinCenter(ir);
633 x[0]=radius*TMath::Cos(phi);
634 x[1]=radius*TMath::Sin(phi);
635 for (Int_t iz=1;iz<=nz;++iz) {
636 x[2]=h->GetXaxis()->GetBinCenter(iz);
637 Int_t roc=x[2]>0.?0:18; // FIXME
638 GetCorrection(x,roc,dx);
639 Float_t r0=TMath::Sqrt((x[0] )*(x[0] )+(x[1] )*(x[1] ));
640 Float_t r1=TMath::Sqrt((x[0]+dx[0])*(x[0]+dx[0])+(x[1]+dx[1])*(x[1]+dx[1]));
641 h->SetBinContent(iz,ir,r1-r0);
642 }
643 }
0116859c 644 return h;
645
646}
647
648TH2F* AliTPCCorrection::CreateHistoDRPhiinZR(Float_t phi,Int_t nz,Int_t nr) {
7d855b04 649 /// Simple plot functionality.
650 /// Returns a 2d hisogram which represents the corrections in rphi direction (drphi)
651 /// in respect to angle phi within the ZR plane.
652 /// The histogramm has nx times ny entries.
653
4e8fafa8 654 TH2F *h=CreateTH2F("drphi_zr", TString::Format("%s: DRPhiinZR R=%2.2f", GetTitle(),phi).Data(),"z [cm]","r [cm]","drphi [cm]",
0116859c 655 nz,-250.,250.,nr,85.,250.);
656 Float_t x[3],dx[3];
657 for (Int_t iz=1;iz<=nz;++iz) {
658 x[2]=h->GetXaxis()->GetBinCenter(iz);
659 Int_t roc=x[2]>0.?0:18; // FIXME
660 for (Int_t ir=1;ir<=nr;++ir) {
661 Float_t radius=h->GetYaxis()->GetBinCenter(ir);
662 x[0]=radius*TMath::Cos(phi);
663 x[1]=radius*TMath::Sin(phi);
664 GetCorrection(x,roc,dx);
665 Float_t r0=TMath::Sqrt((x[0] )*(x[0] )+(x[1] )*(x[1] ));
666 Float_t phi0=TMath::ATan2(x[1] ,x[0] );
667 Float_t phi1=TMath::ATan2(x[1]+dx[1],x[0]+dx[0]);
7d855b04 668
0116859c 669 Float_t dphi=phi1-phi0;
670 if (dphi<TMath::Pi()) dphi+=TMath::TwoPi();
671 if (dphi>TMath::Pi()) dphi-=TMath::TwoPi();
7d855b04 672
0116859c 673 h->SetBinContent(iz,ir,r0*dphi);
674 }
675 }
676 return h;
677}
678
c9cbd2f2 679TH2F* AliTPCCorrection::CreateHistoDZinZR(Float_t phi,Int_t nz,Int_t nr) {
7d855b04 680 /// Simple plot functionality.
681 /// Returns a 2d hisogram which represents the corrections in longitudinal direction (dz)
682 /// in respect to angle phi within the ZR plane.
683 /// The histogramm has nx times ny entries.
684
4e8fafa8 685 TH2F *h=CreateTH2F("dz_zr",TString::Format("%s: DZinZR Z=%2.0f", GetTitle(),phi).Data(),"z [cm]","r [cm]","dz [cm]",
c9cbd2f2 686 nz,-250.,250.,nr,85.,250.);
687 Float_t x[3],dx[3];
688 for (Int_t ir=1;ir<=nr;++ir) {
689 Float_t radius=h->GetYaxis()->GetBinCenter(ir);
690 x[0]=radius*TMath::Cos(phi);
691 x[1]=radius*TMath::Sin(phi);
692 for (Int_t iz=1;iz<=nz;++iz) {
693 x[2]=h->GetXaxis()->GetBinCenter(iz);
694 Int_t roc=x[2]>0.?0:18; // FIXME
695 GetCorrection(x,roc,dx);
696 h->SetBinContent(iz,ir,dx[2]);
697 }
698 }
699 return h;
700
701}
702
703
0116859c 704TH2F* AliTPCCorrection::CreateTH2F(const char *name,const char *title,
705 const char *xlabel,const char *ylabel,const char *zlabel,
706 Int_t nbinsx,Double_t xlow,Double_t xup,
707 Int_t nbinsy,Double_t ylow,Double_t yup) {
7d855b04 708 /// Helper function to create a 2d histogramm of given size
709
0116859c 710 TString hname=name;
711 Int_t i=0;
712 if (gDirectory) {
713 while (gDirectory->FindObject(hname.Data())) {
714 hname =name;
715 hname+="_";
716 hname+=i;
717 ++i;
718 }
719 }
720 TH2F *h=new TH2F(hname.Data(),title,
721 nbinsx,xlow,xup,
722 nbinsy,ylow,yup);
723 h->GetXaxis()->SetTitle(xlabel);
724 h->GetYaxis()->SetTitle(ylabel);
725 h->GetZaxis()->SetTitle(zlabel);
726 h->SetStats(0);
727 return h;
728}
729
0116859c 730// Simple Interpolation functions: e.g. with bi(tri)cubic interpolations (not yet in TH2 and TH3)
731
7d855b04 732void AliTPCCorrection::Interpolate2DEdistortion( Int_t order, Double_t r, Double_t z,
b1f0a2a5 733 const Double_t er[kNZ][kNR], Double_t &erValue ) {
7d855b04 734 /// Interpolate table - 2D interpolation
735
25732bff 736 Double_t saveEr[5] = {0,0,0,0,0};
0116859c 737
738 Search( kNZ, fgkZList, z, fJLow ) ;
739 Search( kNR, fgkRList, r, fKLow ) ;
740 if ( fJLow < 0 ) fJLow = 0 ; // check if out of range
741 if ( fKLow < 0 ) fKLow = 0 ;
742 if ( fJLow + order >= kNZ - 1 ) fJLow = kNZ - 1 - order ;
743 if ( fKLow + order >= kNR - 1 ) fKLow = kNR - 1 - order ;
744
745 for ( Int_t j = fJLow ; j < fJLow + order + 1 ; j++ ) {
b1f0a2a5 746 saveEr[j-fJLow] = Interpolate( &fgkRList[fKLow], &er[j][fKLow], order, r ) ;
0116859c 747 }
b1f0a2a5 748 erValue = Interpolate( &fgkZList[fJLow], saveEr, order, z ) ;
0116859c 749
750}
751
7d855b04 752void AliTPCCorrection::Interpolate3DEdistortion( Int_t order, Double_t r, Float_t phi, Double_t z,
c9cbd2f2 753 const Double_t er[kNZ][kNPhi][kNR], const Double_t ephi[kNZ][kNPhi][kNR], const Double_t ez[kNZ][kNPhi][kNR],
754 Double_t &erValue, Double_t &ephiValue, Double_t &ezValue) {
7d855b04 755 /// Interpolate table - 3D interpolation
756
25732bff 757 Double_t saveEr[5]= {0,0,0,0,0};
758 Double_t savedEr[5]= {0,0,0,0,0} ;
759
760 Double_t saveEphi[5]= {0,0,0,0,0};
761 Double_t savedEphi[5]= {0,0,0,0,0} ;
762
763 Double_t saveEz[5]= {0,0,0,0,0};
764 Double_t savedEz[5]= {0,0,0,0,0} ;
c9cbd2f2 765
766 Search( kNZ, fgkZList, z, fILow ) ;
767 Search( kNPhi, fgkPhiList, z, fJLow ) ;
768 Search( kNR, fgkRList, r, fKLow ) ;
769
770 if ( fILow < 0 ) fILow = 0 ; // check if out of range
771 if ( fJLow < 0 ) fJLow = 0 ;
772 if ( fKLow < 0 ) fKLow = 0 ;
773
774 if ( fILow + order >= kNZ - 1 ) fILow = kNZ - 1 - order ;
775 if ( fJLow + order >= kNPhi - 1 ) fJLow = kNPhi - 1 - order ;
776 if ( fKLow + order >= kNR - 1 ) fKLow = kNR - 1 - order ;
777
778 for ( Int_t i = fILow ; i < fILow + order + 1 ; i++ ) {
779 for ( Int_t j = fJLow ; j < fJLow + order + 1 ; j++ ) {
780 saveEr[j-fJLow] = Interpolate( &fgkRList[fKLow], &er[i][j][fKLow], order, r ) ;
781 saveEphi[j-fJLow] = Interpolate( &fgkRList[fKLow], &ephi[i][j][fKLow], order, r ) ;
782 saveEz[j-fJLow] = Interpolate( &fgkRList[fKLow], &ez[i][j][fKLow], order, r ) ;
783 }
7d855b04 784 savedEr[i-fILow] = Interpolate( &fgkPhiList[fJLow], saveEr, order, phi ) ;
785 savedEphi[i-fILow] = Interpolate( &fgkPhiList[fJLow], saveEphi, order, phi ) ;
786 savedEz[i-fILow] = Interpolate( &fgkPhiList[fJLow], saveEz, order, phi ) ;
c9cbd2f2 787 }
788 erValue = Interpolate( &fgkZList[fILow], savedEr, order, z ) ;
789 ephiValue = Interpolate( &fgkZList[fILow], savedEphi, order, z ) ;
790 ezValue = Interpolate( &fgkZList[fILow], savedEz, order, z ) ;
791
792}
793
7d855b04 794Double_t AliTPCCorrection::Interpolate2DTable( Int_t order, Double_t x, Double_t y,
795 Int_t nx, Int_t ny, const Double_t xv[], const Double_t yv[],
c9cbd2f2 796 const TMatrixD &array ) {
7d855b04 797 /// Interpolate table (TMatrix format) - 2D interpolation
c9cbd2f2 798
799 static Int_t jlow = 0, klow = 0 ;
25732bff 800 Double_t saveArray[5] = {0,0,0,0,0} ;
c9cbd2f2 801
802 Search( nx, xv, x, jlow ) ;
803 Search( ny, yv, y, klow ) ;
804 if ( jlow < 0 ) jlow = 0 ; // check if out of range
805 if ( klow < 0 ) klow = 0 ;
806 if ( jlow + order >= nx - 1 ) jlow = nx - 1 - order ;
807 if ( klow + order >= ny - 1 ) klow = ny - 1 - order ;
808
809 for ( Int_t j = jlow ; j < jlow + order + 1 ; j++ )
810 {
811 Double_t *ajkl = &((TMatrixD&)array)(j,klow);
812 saveArray[j-jlow] = Interpolate( &yv[klow], ajkl , order, y ) ;
813 }
814
815 return( Interpolate( &xv[jlow], saveArray, order, x ) ) ;
816
817}
818
5a516e0a 819Double_t AliTPCCorrection::Interpolate3DTable( Int_t order, Double_t x, Double_t y, Double_t z,
820 Int_t nx, Int_t ny, Int_t nz,
c9cbd2f2 821 const Double_t xv[], const Double_t yv[], const Double_t zv[],
822 TMatrixD **arrayofArrays ) {
7d855b04 823 /// Interpolate table (TMatrix format) - 3D interpolation
c9cbd2f2 824
825 static Int_t ilow = 0, jlow = 0, klow = 0 ;
25732bff 826 Double_t saveArray[5]= {0,0,0,0,0};
827 Double_t savedArray[5]= {0,0,0,0,0} ;
c9cbd2f2 828
829 Search( nx, xv, x, ilow ) ;
830 Search( ny, yv, y, jlow ) ;
7d855b04 831 Search( nz, zv, z, klow ) ;
c9cbd2f2 832
833 if ( ilow < 0 ) ilow = 0 ; // check if out of range
834 if ( jlow < 0 ) jlow = 0 ;
835 if ( klow < 0 ) klow = 0 ;
836
837 if ( ilow + order >= nx - 1 ) ilow = nx - 1 - order ;
838 if ( jlow + order >= ny - 1 ) jlow = ny - 1 - order ;
839 if ( klow + order >= nz - 1 ) klow = nz - 1 - order ;
840
841 for ( Int_t k = klow ; k < klow + order + 1 ; k++ )
842 {
843 TMatrixD &table = *arrayofArrays[k] ;
844 for ( Int_t i = ilow ; i < ilow + order + 1 ; i++ )
845 {
846 saveArray[i-ilow] = Interpolate( &yv[jlow], &table(i,jlow), order, y ) ;
847 }
7d855b04 848 savedArray[k-klow] = Interpolate( &xv[ilow], saveArray, order, x ) ;
c9cbd2f2 849 }
850 return( Interpolate( &zv[klow], savedArray, order, z ) ) ;
851
852}
853
7d855b04 854Double_t AliTPCCorrection::Interpolate( const Double_t xArray[], const Double_t yArray[],
5a516e0a 855 Int_t order, Double_t x ) {
7d855b04 856 /// Interpolate function Y(x) using linear (order=1) or quadratic (order=2) interpolation.
0116859c 857
858 Double_t y ;
7d855b04 859 if ( order == 2 ) { // Quadratic Interpolation = 2
860 y = (x-xArray[1]) * (x-xArray[2]) * yArray[0] / ( (xArray[0]-xArray[1]) * (xArray[0]-xArray[2]) ) ;
861 y += (x-xArray[2]) * (x-xArray[0]) * yArray[1] / ( (xArray[1]-xArray[2]) * (xArray[1]-xArray[0]) ) ;
862 y += (x-xArray[0]) * (x-xArray[1]) * yArray[2] / ( (xArray[2]-xArray[0]) * (xArray[2]-xArray[1]) ) ;
0116859c 863 } else { // Linear Interpolation = 1
864 y = yArray[0] + ( yArray[1]-yArray[0] ) * ( x-xArray[0] ) / ( xArray[1] - xArray[0] ) ;
865 }
866
867 return (y);
868
869}
870
7d855b04 871Float_t AliTPCCorrection::Interpolate2DTable( Int_t order, Double_t x, Double_t y,
872 Int_t nx, Int_t ny, const Double_t xv[], const Double_t yv[],
2bf29b72 873 const TMatrixF &array ) {
7d855b04 874 /// Interpolate table (TMatrix format) - 2D interpolation
875 /// Float version (in order to decrease the OCDB size)
2bf29b72 876
877 static Int_t jlow = 0, klow = 0 ;
878 Float_t saveArray[5] = {0.,0.,0.,0.,0.} ;
879
880 Search( nx, xv, x, jlow ) ;
881 Search( ny, yv, y, klow ) ;
882 if ( jlow < 0 ) jlow = 0 ; // check if out of range
883 if ( klow < 0 ) klow = 0 ;
884 if ( jlow + order >= nx - 1 ) jlow = nx - 1 - order ;
885 if ( klow + order >= ny - 1 ) klow = ny - 1 - order ;
886
887 for ( Int_t j = jlow ; j < jlow + order + 1 ; j++ )
888 {
889 Float_t *ajkl = &((TMatrixF&)array)(j,klow);
890 saveArray[j-jlow] = Interpolate( &yv[klow], ajkl , order, y ) ;
891 }
892
893 return( Interpolate( &xv[jlow], saveArray, order, x ) ) ;
894
895}
896
5a516e0a 897Float_t AliTPCCorrection::Interpolate3DTable( Int_t order, Double_t x, Double_t y, Double_t z,
898 Int_t nx, Int_t ny, Int_t nz,
2bf29b72 899 const Double_t xv[], const Double_t yv[], const Double_t zv[],
900 TMatrixF **arrayofArrays ) {
7d855b04 901 /// Interpolate table (TMatrix format) - 3D interpolation
902 /// Float version (in order to decrease the OCDB size)
2bf29b72 903
904 static Int_t ilow = 0, jlow = 0, klow = 0 ;
905 Float_t saveArray[5]= {0.,0.,0.,0.,0.};
906 Float_t savedArray[5]= {0.,0.,0.,0.,0.} ;
907
908 Search( nx, xv, x, ilow ) ;
909 Search( ny, yv, y, jlow ) ;
7d855b04 910 Search( nz, zv, z, klow ) ;
2bf29b72 911
912 if ( ilow < 0 ) ilow = 0 ; // check if out of range
913 if ( jlow < 0 ) jlow = 0 ;
914 if ( klow < 0 ) klow = 0 ;
915
916 if ( ilow + order >= nx - 1 ) ilow = nx - 1 - order ;
917 if ( jlow + order >= ny - 1 ) jlow = ny - 1 - order ;
918 if ( klow + order >= nz - 1 ) klow = nz - 1 - order ;
919
920 for ( Int_t k = klow ; k < klow + order + 1 ; k++ )
921 {
922 TMatrixF &table = *arrayofArrays[k] ;
923 for ( Int_t i = ilow ; i < ilow + order + 1 ; i++ )
924 {
925 saveArray[i-ilow] = Interpolate( &yv[jlow], &table(i,jlow), order, y ) ;
926 }
7d855b04 927 savedArray[k-klow] = Interpolate( &xv[ilow], saveArray, order, x ) ;
2bf29b72 928 }
929 return( Interpolate( &zv[klow], savedArray, order, z ) ) ;
930
931}
7d855b04 932Float_t AliTPCCorrection::Interpolate( const Double_t xArray[], const Float_t yArray[],
5a516e0a 933 Int_t order, Double_t x ) {
7d855b04 934 /// Interpolate function Y(x) using linear (order=1) or quadratic (order=2) interpolation.
935 /// Float version (in order to decrease the OCDB size)
2bf29b72 936
937 Float_t y ;
7d855b04 938 if ( order == 2 ) { // Quadratic Interpolation = 2
939 y = (x-xArray[1]) * (x-xArray[2]) * yArray[0] / ( (xArray[0]-xArray[1]) * (xArray[0]-xArray[2]) ) ;
940 y += (x-xArray[2]) * (x-xArray[0]) * yArray[1] / ( (xArray[1]-xArray[2]) * (xArray[1]-xArray[0]) ) ;
941 y += (x-xArray[0]) * (x-xArray[1]) * yArray[2] / ( (xArray[2]-xArray[0]) * (xArray[2]-xArray[1]) ) ;
2bf29b72 942 } else { // Linear Interpolation = 1
943 y = yArray[0] + ( yArray[1]-yArray[0] ) * ( x-xArray[0] ) / ( xArray[1] - xArray[0] ) ;
944 }
945
946 return (y);
947
948}
949
950
0116859c 951
5a516e0a 952void AliTPCCorrection::Search( Int_t n, const Double_t xArray[], Double_t x, Int_t &low ) {
7d855b04 953 /// Search an ordered table by starting at the most recently used point
0116859c 954
955 Long_t middle, high ;
956 Int_t ascend = 0, increment = 1 ;
957
958 if ( xArray[n-1] >= xArray[0] ) ascend = 1 ; // Ascending ordered table if true
7d855b04 959
960 if ( low < 0 || low > n-1 ) {
961 low = -1 ; high = n ;
0116859c 962 } else { // Ordered Search phase
963 if ( (Int_t)( x >= xArray[low] ) == ascend ) {
7d855b04 964 if ( low == n-1 ) return ;
0116859c 965 high = low + 1 ;
966 while ( (Int_t)( x >= xArray[high] ) == ascend ) {
967 low = high ;
968 increment *= 2 ;
969 high = low + increment ;
970 if ( high > n-1 ) { high = n ; break ; }
971 }
972 } else {
973 if ( low == 0 ) { low = -1 ; return ; }
974 high = low - 1 ;
975 while ( (Int_t)( x < xArray[low] ) == ascend ) {
976 high = low ;
977 increment *= 2 ;
978 if ( increment >= high ) { low = -1 ; break ; }
979 else low = high - increment ;
980 }
981 }
982 }
7d855b04 983
0116859c 984 while ( (high-low) != 1 ) { // Binary Search Phase
985 middle = ( high + low ) / 2 ;
986 if ( (Int_t)( x >= xArray[middle] ) == ascend )
987 low = middle ;
988 else
989 high = middle ;
990 }
7d855b04 991
0116859c 992 if ( x == xArray[n-1] ) low = n-2 ;
993 if ( x == xArray[0] ) low = 0 ;
7d855b04 994
0116859c 995}
996
35ae345f 997void AliTPCCorrection::InitLookUpfulcrums() {
7d855b04 998 /// Initialization of interpolation points - for main look up table
999 /// (course grid in the middle, fine grid on the borders)
35ae345f 1000
1001 AliTPCROC * roc = AliTPCROC::Instance();
7d855b04 1002 const Double_t rLow = TMath::Floor(roc->GetPadRowRadii(0,0))-1; // first padRow plus some margin
35ae345f 1003
1004 // fulcrums in R
1005 fgkRList[0] = rLow;
1006 for (Int_t i = 1; i<kNR; i++) {
7d855b04 1007 fgkRList[i] = fgkRList[i-1] + 3.5; // 3.5 cm spacing
1008 if (fgkRList[i]<90 ||fgkRList[i]>245)
35ae345f 1009 fgkRList[i] = fgkRList[i-1] + 0.5; // 0.5 cm spacing
7d855b04 1010 else if (fgkRList[i]<100 || fgkRList[i]>235)
35ae345f 1011 fgkRList[i] = fgkRList[i-1] + 1.5; // 1.5 cm spacing
7d855b04 1012 else if (fgkRList[i]<120 || fgkRList[i]>225)
35ae345f 1013 fgkRList[i] = fgkRList[i-1] + 2.5; // 2.5 cm spacing
1014 }
1015
1016 // fulcrums in Z
1017 fgkZList[0] = -249.5;
1018 fgkZList[kNZ-1] = 249.5;
1019 for (Int_t j = 1; j<kNZ/2; j++) {
1020 fgkZList[j] = fgkZList[j-1];
1021 if (TMath::Abs(fgkZList[j])< 0.15)
1022 fgkZList[j] = fgkZList[j-1] + 0.09; // 0.09 cm spacing
1023 else if(TMath::Abs(fgkZList[j])< 0.6)
1024 fgkZList[j] = fgkZList[j-1] + 0.4; // 0.4 cm spacing
7d855b04 1025 else if (TMath::Abs(fgkZList[j])< 2.5 || TMath::Abs(fgkZList[j])>248)
35ae345f 1026 fgkZList[j] = fgkZList[j-1] + 0.5; // 0.5 cm spacing
7d855b04 1027 else if (TMath::Abs(fgkZList[j])<10 || TMath::Abs(fgkZList[j])>235)
35ae345f 1028 fgkZList[j] = fgkZList[j-1] + 1.5; // 1.5 cm spacing
7d855b04 1029 else if (TMath::Abs(fgkZList[j])<25 || TMath::Abs(fgkZList[j])>225)
35ae345f 1030 fgkZList[j] = fgkZList[j-1] + 2.5; // 2.5 cm spacing
7d855b04 1031 else
35ae345f 1032 fgkZList[j] = fgkZList[j-1] + 4; // 4 cm spacing
1033
1034 fgkZList[kNZ-j-1] = -fgkZList[j];
1035 }
7d855b04 1036
35ae345f 1037 // fulcrums in phi
7d855b04 1038 for (Int_t k = 0; k<kNPhi; k++)
1039 fgkPhiList[k] = TMath::TwoPi()*k/(kNPhi-1);
1040
1041
35ae345f 1042}
1043
1044
7d855b04 1045void AliTPCCorrection::PoissonRelaxation2D(TMatrixD &arrayV, TMatrixD &chargeDensity,
1046 TMatrixD &arrayErOverEz, TMatrixD &arrayDeltaEz,
5a516e0a 1047 Int_t rows, Int_t columns, Int_t iterations,
1048 Bool_t rocDisplacement ) {
7d855b04 1049 /// Solve Poisson's Equation by Relaxation Technique in 2D (assuming cylindrical symmetry)
1050 ///
1051 /// Solve Poissons equation in a cylindrical coordinate system. The arrayV matrix must be filled with the
1052 /// boundary conditions on the first and last rows, and the first and last columns. The remainder of the
1053 /// array can be blank or contain a preliminary guess at the solution. The Charge density matrix contains
1054 /// the enclosed spacecharge density at each point. The charge density matrix can be full of zero's if
1055 /// you wish to solve Laplaces equation however it should not contain random numbers or you will get
1056 /// random numbers back as a solution.
1057 /// Poisson's equation is solved by iteratively relaxing the matrix to the final solution. In order to
1058 /// speed up the convergence to the best solution, this algorithm does a binary expansion of the solution
1059 /// space. First it solves the problem on a very sparse grid by skipping rows and columns in the original
1060 /// matrix. Then it doubles the number of points and solves the problem again. Then it doubles the
1061 /// number of points and solves the problem again. This happens several times until the maximum number
1062 /// of points has been included in the array.
1063 ///
1064 /// NOTE: In order for this algorithmto work, the number of rows and columns must be a power of 2 plus one.
1065 /// So rows == 2**M + 1 and columns == 2**N + 1. The number of rows and columns can be different.
1066 ///
1067 /// NOTE: rocDisplacement is used to include (or ignore) the ROC misalignment in the dz calculation
1068 ///
1069 /// Original code by Jim Thomas (STAR TPC Collaboration)
1070
1071 Double_t ezField = (fgkCathodeV-fgkGG)/fgkTPCZ0; // = ALICE Electric Field (V/cm) Magnitude ~ -400 V/cm;
1b923461 1072
1073 const Float_t gridSizeR = (fgkOFCRadius-fgkIFCRadius) / (rows-1) ;
1074 const Float_t gridSizeZ = fgkTPCZ0 / (columns-1) ;
1075 const Float_t ratio = gridSizeR*gridSizeR / (gridSizeZ*gridSizeZ) ;
1076
1077 TMatrixD arrayEr(rows,columns) ;
1078 TMatrixD arrayEz(rows,columns) ;
1079
1080 //Check that number of rows and columns is suitable for a binary expansion
7d855b04 1081
1b923461 1082 if ( !IsPowerOfTwo(rows-1) ) {
1083 AliError("PoissonRelaxation - Error in the number of rows. Must be 2**M - 1");
1084 return;
1085 }
1086 if ( !IsPowerOfTwo(columns-1) ) {
1087 AliError("PoissonRelaxation - Error in the number of columns. Must be 2**N - 1");
1088 return;
1089 }
7d855b04 1090
1b923461 1091 // Solve Poisson's equation in cylindrical coordinates by relaxation technique
1092 // Allow for different size grid spacing in R and Z directions
1093 // Use a binary expansion of the size of the matrix to speed up the solution of the problem
7d855b04 1094
1b923461 1095 Int_t iOne = (rows-1)/4 ;
1096 Int_t jOne = (columns-1)/4 ;
1097 // Solve for N in 2**N, add one.
7d855b04 1098 Int_t loops = 1 + (int) ( 0.5 + TMath::Log2( (double) TMath::Max(iOne,jOne) ) ) ;
1b923461 1099
7d855b04 1100 for ( Int_t count = 0 ; count < loops ; count++ ) {
1b923461 1101 // Loop while the matrix expands & the resolution increases.
1102
1103 Float_t tempGridSizeR = gridSizeR * iOne ;
1104 Float_t tempRatio = ratio * iOne * iOne / ( jOne * jOne ) ;
1105 Float_t tempFourth = 1.0 / (2.0 + 2.0*tempRatio) ;
7d855b04 1106
1b923461 1107 // Do this the standard C++ way to avoid gcc extensions for Float_t coef1[rows]
7d855b04 1108 std::vector<float> coef1(rows) ;
1109 std::vector<float> coef2(rows) ;
1b923461 1110
1111 for ( Int_t i = iOne ; i < rows-1 ; i+=iOne ) {
1112 Float_t radius = fgkIFCRadius + i*gridSizeR ;
1113 coef1[i] = 1.0 + tempGridSizeR/(2*radius);
1114 coef2[i] = 1.0 - tempGridSizeR/(2*radius);
1115 }
7d855b04 1116
1b923461 1117 TMatrixD sumChargeDensity(rows,columns) ;
1118
1119 for ( Int_t i = iOne ; i < rows-1 ; i += iOne ) {
1120 Float_t radius = fgkIFCRadius + iOne*gridSizeR ;
1121 for ( Int_t j = jOne ; j < columns-1 ; j += jOne ) {
1122 if ( iOne == 1 && jOne == 1 ) sumChargeDensity(i,j) = chargeDensity(i,j) ;
7d855b04 1123 else {
1b923461 1124 // Add up all enclosed charge density contributions within 1/2 unit in all directions
1125 Float_t weight = 0.0 ;
1126 Float_t sum = 0.0 ;
1127 sumChargeDensity(i,j) = 0.0 ;
1128 for ( Int_t ii = i-iOne/2 ; ii <= i+iOne/2 ; ii++ ) {
1129 for ( Int_t jj = j-jOne/2 ; jj <= j+jOne/2 ; jj++ ) {
1130 if ( ii == i-iOne/2 || ii == i+iOne/2 || jj == j-jOne/2 || jj == j+jOne/2 ) weight = 0.5 ;
1131 else
1132 weight = 1.0 ;
1133 // Note that this is cylindrical geometry
7d855b04 1134 sumChargeDensity(i,j) += chargeDensity(ii,jj)*weight*radius ;
1b923461 1135 sum += weight*radius ;
1136 }
1137 }
1138 sumChargeDensity(i,j) /= sum ;
1139 }
1140 sumChargeDensity(i,j) *= tempGridSizeR*tempGridSizeR; // just saving a step later on
1141 }
1142 }
1143
7d855b04 1144 for ( Int_t k = 1 ; k <= iterations; k++ ) {
1b923461 1145 // Solve Poisson's Equation
7d855b04 1146 // Over-relaxation index, must be >= 1 but < 2. Arrange for it to evolve from 2 => 1
1b923461 1147 // as interations increase.
7d855b04 1148 Float_t overRelax = 1.0 + TMath::Sqrt( TMath::Cos( (k*TMath::PiOver2())/iterations ) ) ;
1b923461 1149 Float_t overRelaxM1 = overRelax - 1.0 ;
1150 Float_t overRelaxtempFourth, overRelaxcoef5 ;
1151 overRelaxtempFourth = overRelax * tempFourth ;
7d855b04 1152 overRelaxcoef5 = overRelaxM1 / overRelaxtempFourth ;
1b923461 1153
1154 for ( Int_t i = iOne ; i < rows-1 ; i += iOne ) {
1155 for ( Int_t j = jOne ; j < columns-1 ; j += jOne ) {
1156
1157 arrayV(i,j) = ( coef2[i] * arrayV(i-iOne,j)
1158 + tempRatio * ( arrayV(i,j-jOne) + arrayV(i,j+jOne) )
7d855b04 1159 - overRelaxcoef5 * arrayV(i,j)
1160 + coef1[i] * arrayV(i+iOne,j)
1161 + sumChargeDensity(i,j)
1b923461 1162 ) * overRelaxtempFourth;
1163 }
1164 }
1165
7d855b04 1166 if ( k == iterations ) {
1b923461 1167 // After full solution is achieved, copy low resolution solution into higher res array
1168 for ( Int_t i = iOne ; i < rows-1 ; i += iOne ) {
1169 for ( Int_t j = jOne ; j < columns-1 ; j += jOne ) {
1170
7d855b04 1171 if ( iOne > 1 ) {
1b923461 1172 arrayV(i+iOne/2,j) = ( arrayV(i+iOne,j) + arrayV(i,j) ) / 2 ;
1173 if ( i == iOne ) arrayV(i-iOne/2,j) = ( arrayV(0,j) + arrayV(iOne,j) ) / 2 ;
1174 }
1175 if ( jOne > 1 ) {
1176 arrayV(i,j+jOne/2) = ( arrayV(i,j+jOne) + arrayV(i,j) ) / 2 ;
1177 if ( j == jOne ) arrayV(i,j-jOne/2) = ( arrayV(i,0) + arrayV(i,jOne) ) / 2 ;
1178 }
1179 if ( iOne > 1 && jOne > 1 ) {
1180 arrayV(i+iOne/2,j+jOne/2) = ( arrayV(i+iOne,j+jOne) + arrayV(i,j) ) / 2 ;
1181 if ( i == iOne ) arrayV(i-iOne/2,j-jOne/2) = ( arrayV(0,j-jOne) + arrayV(iOne,j) ) / 2 ;
1182 if ( j == jOne ) arrayV(i-iOne/2,j-jOne/2) = ( arrayV(i-iOne,0) + arrayV(i,jOne) ) / 2 ;
7d855b04 1183 // Note that this leaves a point at the upper left and lower right corners uninitialized.
1b923461 1184 // -> Not a big deal.
1185 }
1186
1187 }
1188 }
1189 }
1190
1191 }
1192
1193 iOne = iOne / 2 ; if ( iOne < 1 ) iOne = 1 ;
1194 jOne = jOne / 2 ; if ( jOne < 1 ) jOne = 1 ;
1195
c9cbd2f2 1196 sumChargeDensity.Clear();
7d855b04 1197 }
1b923461 1198
1199 // Differentiate V(r) and solve for E(r) using special equations for the first and last rows
7d855b04 1200 for ( Int_t j = 0 ; j < columns ; j++ ) {
1b923461 1201 for ( Int_t i = 1 ; i < rows-1 ; i++ ) arrayEr(i,j) = -1 * ( arrayV(i+1,j) - arrayV(i-1,j) ) / (2*gridSizeR) ;
7d855b04 1202 arrayEr(0,j) = -1 * ( -0.5*arrayV(2,j) + 2.0*arrayV(1,j) - 1.5*arrayV(0,j) ) / gridSizeR ;
1203 arrayEr(rows-1,j) = -1 * ( 1.5*arrayV(rows-1,j) - 2.0*arrayV(rows-2,j) + 0.5*arrayV(rows-3,j) ) / gridSizeR ;
1b923461 1204 }
1205
1206 // Differentiate V(z) and solve for E(z) using special equations for the first and last columns
1207 for ( Int_t i = 0 ; i < rows ; i++) {
1208 for ( Int_t j = 1 ; j < columns-1 ; j++ ) arrayEz(i,j) = -1 * ( arrayV(i,j+1) - arrayV(i,j-1) ) / (2*gridSizeZ) ;
7d855b04 1209 arrayEz(i,0) = -1 * ( -0.5*arrayV(i,2) + 2.0*arrayV(i,1) - 1.5*arrayV(i,0) ) / gridSizeZ ;
1210 arrayEz(i,columns-1) = -1 * ( 1.5*arrayV(i,columns-1) - 2.0*arrayV(i,columns-2) + 0.5*arrayV(i,columns-3) ) / gridSizeZ ;
1b923461 1211 }
7d855b04 1212
1b923461 1213 for ( Int_t i = 0 ; i < rows ; i++) {
1214 // Note: go back and compare to old version of this code. See notes below.
1215 // JT Test ... attempt to divide by real Ez not Ez to first order
1216 for ( Int_t j = 0 ; j < columns ; j++ ) {
1217 arrayEz(i,j) += ezField;
1218 // This adds back the overall Z gradient of the field (main E field component)
7d855b04 1219 }
1b923461 1220 // Warning: (-=) assumes you are using an error potetial without the overall Field included
7d855b04 1221 }
1222
1b923461 1223 // Integrate Er/Ez from Z to zero
7d855b04 1224 for ( Int_t j = 0 ; j < columns ; j++ ) {
1b923461 1225 for ( Int_t i = 0 ; i < rows ; i++ ) {
7d855b04 1226
1227 Int_t index = 1 ; // Simpsons rule if N=odd. If N!=odd then add extra point by trapezoidal rule.
1b923461 1228 arrayErOverEz(i,j) = 0.0 ;
c9cbd2f2 1229 arrayDeltaEz(i,j) = 0.0 ;
7d855b04 1230
1b923461 1231 for ( Int_t k = j ; k < columns ; k++ ) {
1232 arrayErOverEz(i,j) += index*(gridSizeZ/3.0)*arrayEr(i,k)/arrayEz(i,k) ;
c9cbd2f2 1233 arrayDeltaEz(i,j) += index*(gridSizeZ/3.0)*(arrayEz(i,k)-ezField) ;
1b923461 1234 if ( index != 4 ) index = 4; else index = 2 ;
1235 }
c9cbd2f2 1236 if ( index == 4 ) {
1237 arrayErOverEz(i,j) -= (gridSizeZ/3.0)*arrayEr(i,columns-1)/arrayEz(i,columns-1) ;
1238 arrayDeltaEz(i,j) -= (gridSizeZ/3.0)*(arrayEz(i,columns-1)-ezField) ;
1239 }
1240 if ( index == 2 ) {
7d855b04 1241 arrayErOverEz(i,j) += (gridSizeZ/3.0) * ( 0.5*arrayEr(i,columns-2)/arrayEz(i,columns-2)
c9cbd2f2 1242 -2.5*arrayEr(i,columns-1)/arrayEz(i,columns-1));
7d855b04 1243 arrayDeltaEz(i,j) += (gridSizeZ/3.0) * ( 0.5*(arrayEz(i,columns-2)-ezField)
c9cbd2f2 1244 -2.5*(arrayEz(i,columns-1)-ezField));
1245 }
1246 if ( j == columns-2 ) {
1247 arrayErOverEz(i,j) = (gridSizeZ/3.0) * ( 1.5*arrayEr(i,columns-2)/arrayEz(i,columns-2)
1248 +1.5*arrayEr(i,columns-1)/arrayEz(i,columns-1) ) ;
1249 arrayDeltaEz(i,j) = (gridSizeZ/3.0) * ( 1.5*(arrayEz(i,columns-2)-ezField)
1250 +1.5*(arrayEz(i,columns-1)-ezField) ) ;
1251 }
1252 if ( j == columns-1 ) {
1253 arrayErOverEz(i,j) = 0.0 ;
1254 arrayDeltaEz(i,j) = 0.0 ;
1255 }
1b923461 1256 }
1257 }
7d855b04 1258
c9cbd2f2 1259 // calculate z distortion from the integrated Delta Ez residuals
1260 // and include the aquivalence (Volt to cm) of the ROC shift !!
1261
7d855b04 1262 for ( Int_t j = 0 ; j < columns ; j++ ) {
c9cbd2f2 1263 for ( Int_t i = 0 ; i < rows ; i++ ) {
1264
1265 // Scale the Ez distortions with the drift velocity pertubation -> delivers cm
1266 arrayDeltaEz(i,j) = arrayDeltaEz(i,j)*fgkdvdE;
1267
1268 // ROC Potential in cm aquivalent
7d855b04 1269 Double_t dzROCShift = arrayV(i, columns -1)/ezField;
c9cbd2f2 1270 if ( rocDisplacement ) arrayDeltaEz(i,j) = arrayDeltaEz(i,j) + dzROCShift; // add the ROC misaligment
1271
1272 }
1273 }
7d855b04 1274
c9cbd2f2 1275 arrayEr.Clear();
1276 arrayEz.Clear();
1277
1b923461 1278}
1279
7d855b04 1280void AliTPCCorrection::PoissonRelaxation3D( TMatrixD**arrayofArrayV, TMatrixD**arrayofChargeDensities,
c9cbd2f2 1281 TMatrixD**arrayofEroverEz, TMatrixD**arrayofEPhioverEz, TMatrixD**arrayofDeltaEz,
7d855b04 1282 Int_t rows, Int_t columns, Int_t phislices,
5a516e0a 1283 Float_t deltaphi, Int_t iterations, Int_t symmetry,
c9cbd2f2 1284 Bool_t rocDisplacement ) {
7d855b04 1285 /// 3D - Solve Poisson's Equation in 3D by Relaxation Technique
1286 ///
1287 /// NOTE: In order for this algorith to work, the number of rows and columns must be a power of 2 plus one.
1288 /// The number of rows and COLUMNS can be different.
1289 ///
1290 /// ROWS == 2**M + 1
1291 /// COLUMNS == 2**N + 1
1292 /// PHISLICES == Arbitrary but greater than 3
1293 ///
1294 /// DeltaPhi in Radians
1295 ///
1296 /// SYMMETRY = 0 if no phi symmetries, and no phi boundary conditions
1297 /// = 1 if we have reflection symmetry at the boundaries (eg. sector symmetry or half sector symmetries).
1298 ///
1299 /// NOTE: rocDisplacement is used to include (or ignore) the ROC misalignment in the dz calculation
1300
1301 const Double_t ezField = (fgkCathodeV-fgkGG)/fgkTPCZ0; // = ALICE Electric Field (V/cm) Magnitude ~ -400 V/cm;
c9cbd2f2 1302
1303 const Float_t gridSizeR = (fgkOFCRadius-fgkIFCRadius) / (rows-1) ;
1304 const Float_t gridSizePhi = deltaphi ;
1305 const Float_t gridSizeZ = fgkTPCZ0 / (columns-1) ;
1306 const Float_t ratioPhi = gridSizeR*gridSizeR / (gridSizePhi*gridSizePhi) ;
1307 const Float_t ratioZ = gridSizeR*gridSizeR / (gridSizeZ*gridSizeZ) ;
1308
1309 TMatrixD arrayE(rows,columns) ;
1310
1311 // Check that the number of rows and columns is suitable for a binary expansion
7d855b04 1312 if ( !IsPowerOfTwo((rows-1)) ) {
1313 AliError("Poisson3DRelaxation - Error in the number of rows. Must be 2**M - 1");
c9cbd2f2 1314 return; }
7d855b04 1315 if ( !IsPowerOfTwo((columns-1)) ) {
c9cbd2f2 1316 AliError("Poisson3DRelaxation - Error in the number of columns. Must be 2**N - 1");
1317 return; }
7d855b04 1318 if ( phislices <= 3 ) {
c9cbd2f2 1319 AliError("Poisson3DRelaxation - Error in the number of phislices. Must be larger than 3");
1320 return; }
7d855b04 1321 if ( phislices > 1000 ) {
1322 AliError("Poisson3D phislices > 1000 is not allowed (nor wise) ");
1323 return; }
1324
c9cbd2f2 1325 // Solve Poisson's equation in cylindrical coordinates by relaxation technique
1326 // Allow for different size grid spacing in R and Z directions
1327 // Use a binary expansion of the matrix to speed up the solution of the problem
1328
1329 Int_t loops, mplus, mminus, signplus, signminus ;
1330 Int_t ione = (rows-1)/4 ;
1331 Int_t jone = (columns-1)/4 ;
1332 loops = TMath::Max(ione, jone) ; // Calculate the number of loops for the binary expansion
1333 loops = 1 + (int) ( 0.5 + TMath::Log2((double)loops) ) ; // Solve for N in 2**N
1334
1335 TMatrixD* arrayofSumChargeDensities[1000] ; // Create temporary arrays to store low resolution charge arrays
1336
1337 for ( Int_t i = 0 ; i < phislices ; i++ ) { arrayofSumChargeDensities[i] = new TMatrixD(rows,columns) ; }
d9ef0909 1338 AliSysInfo::AddStamp("3DInit", 10,0,0);
c9cbd2f2 1339
1340 for ( Int_t count = 0 ; count < loops ; count++ ) { // START the master loop and do the binary expansion
d9ef0909 1341 AliSysInfo::AddStamp("3Diter", 20,count,0);
7d855b04 1342
c9cbd2f2 1343 Float_t tempgridSizeR = gridSizeR * ione ;
1344 Float_t tempratioPhi = ratioPhi * ione * ione ; // Used tobe divided by ( m_one * m_one ) when m_one was != 1
1345 Float_t tempratioZ = ratioZ * ione * ione / ( jone * jone ) ;
1346
1347 std::vector<float> coef1(rows) ; // Do this the standard C++ way to avoid gcc extensions for Float_t coef1[rows]
1348 std::vector<float> coef2(rows) ; // Do this the standard C++ way to avoid gcc extensions for Float_t coef1[rows]
1349 std::vector<float> coef3(rows) ; // Do this the standard C++ way to avoid gcc extensions for Float_t coef1[rows]
1350 std::vector<float> coef4(rows) ; // Do this the standard C++ way to avoid gcc extensions for Float_t coef1[rows]
1351
1352 for ( Int_t i = ione ; i < rows-1 ; i+=ione ) {
1353 Float_t radius = fgkIFCRadius + i*gridSizeR ;
1354 coef1[i] = 1.0 + tempgridSizeR/(2*radius);
1355 coef2[i] = 1.0 - tempgridSizeR/(2*radius);
1356 coef3[i] = tempratioPhi/(radius*radius);
1357 coef4[i] = 0.5 / (1.0 + tempratioZ + coef3[i]);
1358 }
1359
1360 for ( Int_t m = 0 ; m < phislices ; m++ ) {
1361 TMatrixD &chargeDensity = *arrayofChargeDensities[m] ;
1362 TMatrixD &sumChargeDensity = *arrayofSumChargeDensities[m] ;
1363 for ( Int_t i = ione ; i < rows-1 ; i += ione ) {
1364 Float_t radius = fgkIFCRadius + i*gridSizeR ;
1365 for ( Int_t j = jone ; j < columns-1 ; j += jone ) {
1366 if ( ione == 1 && jone == 1 ) sumChargeDensity(i,j) = chargeDensity(i,j) ;
1367 else { // Add up all enclosed charge density contributions within 1/2 unit in all directions
1368 Float_t weight = 0.0 ;
1369 Float_t sum = 0.0 ;
1370 sumChargeDensity(i,j) = 0.0 ;
1371 for ( Int_t ii = i-ione/2 ; ii <= i+ione/2 ; ii++ ) {
1372 for ( Int_t jj = j-jone/2 ; jj <= j+jone/2 ; jj++ ) {
1373 if ( ii == i-ione/2 || ii == i+ione/2 || jj == j-jone/2 || jj == j+jone/2 ) weight = 0.5 ;
1374 else
7d855b04 1375 weight = 1.0 ;
1376 sumChargeDensity(i,j) += chargeDensity(ii,jj)*weight*radius ;
c9cbd2f2 1377 sum += weight*radius ;
1378 }
1379 }
1380 sumChargeDensity(i,j) /= sum ;
1381 }
1382 sumChargeDensity(i,j) *= tempgridSizeR*tempgridSizeR; // just saving a step later on
1383 }
1384 }
1385 }
1386
1387 for ( Int_t k = 1 ; k <= iterations; k++ ) {
1388
1389 // over-relaxation index, >= 1 but < 2
7d855b04 1390 Float_t overRelax = 1.0 + TMath::Sqrt( TMath::Cos( (k*TMath::PiOver2())/iterations ) ) ;
c9cbd2f2 1391 Float_t overRelaxM1 = overRelax - 1.0 ;
1392
1393 std::vector<float> overRelaxcoef4(rows) ; // Do this the standard C++ way to avoid gcc extensions
1394 std::vector<float> overRelaxcoef5(rows) ; // Do this the standard C++ way to avoid gcc extensions
1395
7d855b04 1396 for ( Int_t i = ione ; i < rows-1 ; i+=ione ) {
c9cbd2f2 1397 overRelaxcoef4[i] = overRelax * coef4[i] ;
7d855b04 1398 overRelaxcoef5[i] = overRelaxM1 / overRelaxcoef4[i] ;
c9cbd2f2 1399 }
1400
1401 for ( Int_t m = 0 ; m < phislices ; m++ ) {
1402
7d855b04 1403 mplus = m + 1; signplus = 1 ;
c9cbd2f2 1404 mminus = m - 1 ; signminus = 1 ;
1405 if (symmetry==1) { // Reflection symmetry in phi (e.g. symmetry at sector boundaries, or half sectors, etc.)
1406 if ( mplus > phislices-1 ) mplus = phislices - 2 ;
1407 if ( mminus < 0 ) mminus = 1 ;
1408 }
1409 else if (symmetry==-1) { // Anti-symmetry in phi
1410 if ( mplus > phislices-1 ) { mplus = phislices - 2 ; signplus = -1 ; }
7d855b04 1411 if ( mminus < 0 ) { mminus = 1 ; signminus = -1 ; }
c9cbd2f2 1412 }
1413 else { // No Symmetries in phi, no boundaries, the calculation is continuous across all phi
1414 if ( mplus > phislices-1 ) mplus = m + 1 - phislices ;
1415 if ( mminus < 0 ) mminus = m - 1 + phislices ;
1416 }
1417 TMatrixD& arrayV = *arrayofArrayV[m] ;
1418 TMatrixD& arrayVP = *arrayofArrayV[mplus] ;
1419 TMatrixD& arrayVM = *arrayofArrayV[mminus] ;
1420 TMatrixD& sumChargeDensity = *arrayofSumChargeDensities[m] ;
d9ef0909 1421 Double_t *arrayVfast = arrayV.GetMatrixArray();
1422 Double_t *arrayVPfast = arrayVP.GetMatrixArray();
1423 Double_t *arrayVMfast = arrayVM.GetMatrixArray();
1424 Double_t *sumChargeDensityFast=sumChargeDensity.GetMatrixArray();
c9cbd2f2 1425
d9ef0909 1426 if (0){
1427 // slow implementation
1428 for ( Int_t i = ione ; i < rows-1 ; i+=ione ) {
1429 for ( Int_t j = jone ; j < columns-1 ; j+=jone ) {
7d855b04 1430
d9ef0909 1431 arrayV(i,j) = ( coef2[i] * arrayV(i-ione,j)
1432 + tempratioZ * ( arrayV(i,j-jone) + arrayV(i,j+jone) )
7d855b04 1433 - overRelaxcoef5[i] * arrayV(i,j)
1434 + coef1[i] * arrayV(i+ione,j)
d9ef0909 1435 + coef3[i] * ( signplus*arrayVP(i,j) + signminus*arrayVM(i,j) )
7d855b04 1436 + sumChargeDensity(i,j)
1437 ) * overRelaxcoef4[i] ;
1438 // Note: over-relax the solution at each step. This speeds up the convergance.
d9ef0909 1439 }
1440 }
1441 }else{
1442 for ( Int_t i = ione ; i < rows-1 ; i+=ione ) {
1443 Double_t *arrayVfastI = &(arrayVfast[i*columns]);
1444 Double_t *arrayVPfastI = &(arrayVPfast[i*columns]);
1445 Double_t *arrayVMfastI = &(arrayVMfast[i*columns]);
1446 Double_t *sumChargeDensityFastI=&(sumChargeDensityFast[i*columns]);
1447 for ( Int_t j = jone ; j < columns-1 ; j+=jone ) {
ad5a2460 1448 Double_t /*resSlow*/resFast;
d9ef0909 1449// resSlow = ( coef2[i] * arrayV(i-ione,j)
1450// + tempratioZ * ( arrayV(i,j-jone) + arrayV(i,j+jone) )
7d855b04 1451// - overRelaxcoef5[i] * arrayV(i,j)
1452// + coef1[i] * arrayV(i+ione,j)
d9ef0909 1453// + coef3[i] * ( signplus*arrayVP(i,j) + signminus*arrayVM(i,j) )
7d855b04 1454// + sumChargeDensity(i,j)
1455// ) * overRelaxcoef4[i] ;
d9ef0909 1456 resFast = ( coef2[i] * arrayVfastI[j-columns*ione]
1457 + tempratioZ * ( arrayVfastI[j-jone] + arrayVfastI[j+jone] )
7d855b04 1458 - overRelaxcoef5[i] * arrayVfastI[j]
1459 + coef1[i] * arrayVfastI[j+columns*ione]
d9ef0909 1460 + coef3[i] * ( signplus* arrayVPfastI[j] + signminus*arrayVMfastI[j])
7d855b04 1461 + sumChargeDensityFastI[j]
1462 ) * overRelaxcoef4[i] ;
d9ef0909 1463// if (resSlow!=resFast){
1464// printf("problem\t%d\t%d\t%f\t%f\t%f\n",i,j,resFast,resSlow,resFast-resSlow);
1465// }
1466 arrayVfastI[j]=resFast;
7d855b04 1467 // Note: over-relax the solution at each step. This speeds up the convergance.
d9ef0909 1468 }
c9cbd2f2 1469 }
1470 }
1471
1472 if ( k == iterations ) { // After full solution is achieved, copy low resolution solution into higher res array
1473 for ( Int_t i = ione ; i < rows-1 ; i+=ione ) {
1474 for ( Int_t j = jone ; j < columns-1 ; j+=jone ) {
7d855b04 1475
1476 if ( ione > 1 ) {
c9cbd2f2 1477 arrayV(i+ione/2,j) = ( arrayV(i+ione,j) + arrayV(i,j) ) / 2 ;
1478 if ( i == ione ) arrayV(i-ione/2,j) = ( arrayV(0,j) + arrayV(ione,j) ) / 2 ;
1479 }
1480 if ( jone > 1 ) {
1481 arrayV(i,j+jone/2) = ( arrayV(i,j+jone) + arrayV(i,j) ) / 2 ;
1482 if ( j == jone ) arrayV(i,j-jone/2) = ( arrayV(i,0) + arrayV(i,jone) ) / 2 ;
1483 }
1484 if ( ione > 1 && jone > 1 ) {
1485 arrayV(i+ione/2,j+jone/2) = ( arrayV(i+ione,j+jone) + arrayV(i,j) ) / 2 ;
1486 if ( i == ione ) arrayV(i-ione/2,j-jone/2) = ( arrayV(0,j-jone) + arrayV(ione,j) ) / 2 ;
1487 if ( j == jone ) arrayV(i-ione/2,j-jone/2) = ( arrayV(i-ione,0) + arrayV(i,jone) ) / 2 ;
1488 // Note that this leaves a point at the upper left and lower right corners uninitialized. Not a big deal.
1489 }
7d855b04 1490 }
c9cbd2f2 1491 }
1492 }
1493
1494 }
7d855b04 1495 }
c9cbd2f2 1496
1497 ione = ione / 2 ; if ( ione < 1 ) ione = 1 ;
1498 jone = jone / 2 ; if ( jone < 1 ) jone = 1 ;
1499
1500 }
7d855b04 1501
c9cbd2f2 1502 //Differentiate V(r) and solve for E(r) using special equations for the first and last row
1503 //Integrate E(r)/E(z) from point of origin to pad plane
d9ef0909 1504 AliSysInfo::AddStamp("CalcField", 100,0,0);
c9cbd2f2 1505
1506 for ( Int_t m = 0 ; m < phislices ; m++ ) {
1507 TMatrixD& arrayV = *arrayofArrayV[m] ;
1508 TMatrixD& eroverEz = *arrayofEroverEz[m] ;
7d855b04 1509
c9cbd2f2 1510 for ( Int_t j = columns-1 ; j >= 0 ; j-- ) { // Count backwards to facilitate integration over Z
7d855b04 1511
c9cbd2f2 1512 // Differentiate in R
1513 for ( Int_t i = 1 ; i < rows-1 ; i++ ) arrayE(i,j) = -1 * ( arrayV(i+1,j) - arrayV(i-1,j) ) / (2*gridSizeR) ;
7d855b04 1514 arrayE(0,j) = -1 * ( -0.5*arrayV(2,j) + 2.0*arrayV(1,j) - 1.5*arrayV(0,j) ) / gridSizeR ;
1515 arrayE(rows-1,j) = -1 * ( 1.5*arrayV(rows-1,j) - 2.0*arrayV(rows-2,j) + 0.5*arrayV(rows-3,j) ) / gridSizeR ;
c9cbd2f2 1516 // Integrate over Z
1517 for ( Int_t i = 0 ; i < rows ; i++ ) {
7d855b04 1518 Int_t index = 1 ; // Simpsons rule if N=odd. If N!=odd then add extra point by trapezoidal rule.
c9cbd2f2 1519 eroverEz(i,j) = 0.0 ;
1520 for ( Int_t k = j ; k < columns ; k++ ) {
7d855b04 1521
c9cbd2f2 1522 eroverEz(i,j) += index*(gridSizeZ/3.0)*arrayE(i,k)/(-1*ezField) ;
1523 if ( index != 4 ) index = 4; else index = 2 ;
1524 }
1525 if ( index == 4 ) eroverEz(i,j) -= (gridSizeZ/3.0)*arrayE(i,columns-1)/ (-1*ezField) ;
7d855b04 1526 if ( index == 2 ) eroverEz(i,j) +=
c9cbd2f2 1527 (gridSizeZ/3.0)*(0.5*arrayE(i,columns-2)-2.5*arrayE(i,columns-1))/(-1*ezField) ;
7d855b04 1528 if ( j == columns-2 ) eroverEz(i,j) =
c9cbd2f2 1529 (gridSizeZ/3.0)*(1.5*arrayE(i,columns-2)+1.5*arrayE(i,columns-1))/(-1*ezField) ;
1530 if ( j == columns-1 ) eroverEz(i,j) = 0.0 ;
1531 }
1532 }
1533 // if ( m == 0 ) { TCanvas* c1 = new TCanvas("erOverEz","erOverEz",50,50,840,600) ; c1 -> cd() ;
1534 // eroverEz.Draw("surf") ; } // JT test
1535 }
d9ef0909 1536 AliSysInfo::AddStamp("IntegrateEr", 120,0,0);
7d855b04 1537
1538 //Differentiate V(r) and solve for E(phi)
c9cbd2f2 1539 //Integrate E(phi)/E(z) from point of origin to pad plane
1540
1541 for ( Int_t m = 0 ; m < phislices ; m++ ) {
7d855b04 1542
1543 mplus = m + 1; signplus = 1 ;
1544 mminus = m - 1 ; signminus = 1 ;
c9cbd2f2 1545 if (symmetry==1) { // Reflection symmetry in phi (e.g. symmetry at sector boundaries, or half sectors, etc.)
1546 if ( mplus > phislices-1 ) mplus = phislices - 2 ;
1547 if ( mminus < 0 ) mminus = 1 ;
1548 }
1549 else if (symmetry==-1) { // Anti-symmetry in phi
1550 if ( mplus > phislices-1 ) { mplus = phislices - 2 ; signplus = -1 ; }
7d855b04 1551 if ( mminus < 0 ) { mminus = 1 ; signminus = -1 ; }
c9cbd2f2 1552 }
1553 else { // No Symmetries in phi, no boundaries, the calculations is continuous across all phi
1554 if ( mplus > phislices-1 ) mplus = m + 1 - phislices ;
1555 if ( mminus < 0 ) mminus = m - 1 + phislices ;
1556 }
1557 TMatrixD &arrayVP = *arrayofArrayV[mplus] ;
1558 TMatrixD &arrayVM = *arrayofArrayV[mminus] ;
1559 TMatrixD &ePhioverEz = *arrayofEPhioverEz[m] ;
1560 for ( Int_t j = columns-1 ; j >= 0 ; j-- ) { // Count backwards to facilitate integration over Z
1561 // Differentiate in Phi
1562 for ( Int_t i = 0 ; i < rows ; i++ ) {
1563 Float_t radius = fgkIFCRadius + i*gridSizeR ;
1564 arrayE(i,j) = -1 * (signplus * arrayVP(i,j) - signminus * arrayVM(i,j) ) / (2*radius*gridSizePhi) ;
1565 }
1566 // Integrate over Z
1567 for ( Int_t i = 0 ; i < rows ; i++ ) {
7d855b04 1568 Int_t index = 1 ; // Simpsons rule if N=odd. If N!=odd then add extra point by trapezoidal rule.
c9cbd2f2 1569 ePhioverEz(i,j) = 0.0 ;
1570 for ( Int_t k = j ; k < columns ; k++ ) {
7d855b04 1571
c9cbd2f2 1572 ePhioverEz(i,j) += index*(gridSizeZ/3.0)*arrayE(i,k)/(-1*ezField) ;
1573 if ( index != 4 ) index = 4; else index = 2 ;
1574 }
1575 if ( index == 4 ) ePhioverEz(i,j) -= (gridSizeZ/3.0)*arrayE(i,columns-1)/ (-1*ezField) ;
7d855b04 1576 if ( index == 2 ) ePhioverEz(i,j) +=
c9cbd2f2 1577 (gridSizeZ/3.0)*(0.5*arrayE(i,columns-2)-2.5*arrayE(i,columns-1))/(-1*ezField) ;
7d855b04 1578 if ( j == columns-2 ) ePhioverEz(i,j) =
c9cbd2f2 1579 (gridSizeZ/3.0)*(1.5*arrayE(i,columns-2)+1.5*arrayE(i,columns-1))/(-1*ezField) ;
1580 if ( j == columns-1 ) ePhioverEz(i,j) = 0.0 ;
1581 }
1582 }
1583 // if ( m == 5 ) { TCanvas* c2 = new TCanvas("arrayE","arrayE",50,50,840,600) ; c2 -> cd() ;
1584 // arrayE.Draw("surf") ; } // JT test
1585 }
d9ef0909 1586 AliSysInfo::AddStamp("IntegrateEphi", 130,0,0);
7d855b04 1587
c9cbd2f2 1588
1589 // Differentiate V(r) and solve for E(z) using special equations for the first and last row
1590 // Integrate (E(z)-Ezstd) from point of origin to pad plane
7d855b04 1591
c9cbd2f2 1592 for ( Int_t m = 0 ; m < phislices ; m++ ) {
1593 TMatrixD& arrayV = *arrayofArrayV[m] ;
1594 TMatrixD& deltaEz = *arrayofDeltaEz[m] ;
7d855b04 1595
c9cbd2f2 1596 // Differentiate V(z) and solve for E(z) using special equations for the first and last columns
1597 for ( Int_t i = 0 ; i < rows ; i++) {
1598 for ( Int_t j = 1 ; j < columns-1 ; j++ ) arrayE(i,j) = -1 * ( arrayV(i,j+1) - arrayV(i,j-1) ) / (2*gridSizeZ) ;
7d855b04 1599 arrayE(i,0) = -1 * ( -0.5*arrayV(i,2) + 2.0*arrayV(i,1) - 1.5*arrayV(i,0) ) / gridSizeZ ;
1600 arrayE(i,columns-1) = -1 * ( 1.5*arrayV(i,columns-1) - 2.0*arrayV(i,columns-2) + 0.5*arrayV(i,columns-3) ) / gridSizeZ ;
c9cbd2f2 1601 }
7d855b04 1602
c9cbd2f2 1603 for ( Int_t j = columns-1 ; j >= 0 ; j-- ) { // Count backwards to facilitate integration over Z
1604 // Integrate over Z
1605 for ( Int_t i = 0 ; i < rows ; i++ ) {
7d855b04 1606 Int_t index = 1 ; // Simpsons rule if N=odd. If N!=odd then add extra point by trapezoidal rule.
c9cbd2f2 1607 deltaEz(i,j) = 0.0 ;
1608 for ( Int_t k = j ; k < columns ; k++ ) {
1609 deltaEz(i,j) += index*(gridSizeZ/3.0)*arrayE(i,k) ;
1610 if ( index != 4 ) index = 4; else index = 2 ;
1611 }
1612 if ( index == 4 ) deltaEz(i,j) -= (gridSizeZ/3.0)*arrayE(i,columns-1) ;
7d855b04 1613 if ( index == 2 ) deltaEz(i,j) +=
c9cbd2f2 1614 (gridSizeZ/3.0)*(0.5*arrayE(i,columns-2)-2.5*arrayE(i,columns-1)) ;
7d855b04 1615 if ( j == columns-2 ) deltaEz(i,j) =
c9cbd2f2 1616 (gridSizeZ/3.0)*(1.5*arrayE(i,columns-2)+1.5*arrayE(i,columns-1)) ;
1617 if ( j == columns-1 ) deltaEz(i,j) = 0.0 ;
1618 }
1619 }
d9ef0909 1620
c9cbd2f2 1621 // if ( m == 0 ) { TCanvas* c1 = new TCanvas("erOverEz","erOverEz",50,50,840,600) ; c1 -> cd() ;
1622 // eroverEz.Draw("surf") ; } // JT test
7d855b04 1623
c9cbd2f2 1624 // calculate z distortion from the integrated Delta Ez residuals
1625 // and include the aquivalence (Volt to cm) of the ROC shift !!
7d855b04 1626
1627 for ( Int_t j = 0 ; j < columns ; j++ ) {
c9cbd2f2 1628 for ( Int_t i = 0 ; i < rows ; i++ ) {
7d855b04 1629
c9cbd2f2 1630 // Scale the Ez distortions with the drift velocity pertubation -> delivers cm
1631 deltaEz(i,j) = deltaEz(i,j)*fgkdvdE;
7d855b04 1632
c9cbd2f2 1633 // ROC Potential in cm aquivalent
7d855b04 1634 Double_t dzROCShift = arrayV(i, columns -1)/ezField;
c9cbd2f2 1635 if ( rocDisplacement ) deltaEz(i,j) = deltaEz(i,j) + dzROCShift; // add the ROC misaligment
7d855b04 1636
c9cbd2f2 1637 }
1638 }
1639
7d855b04 1640 } // end loop over phi
d9ef0909 1641 AliSysInfo::AddStamp("IntegrateEz", 140,0,0);
7d855b04 1642
c9cbd2f2 1643
1644 for ( Int_t k = 0 ; k < phislices ; k++ )
1645 {
1646 arrayofSumChargeDensities[k]->Delete() ;
1647 }
7d855b04 1648
c9cbd2f2 1649
1650
1651 arrayE.Clear();
1652}
1b923461 1653
1654
710bda39 1655Int_t AliTPCCorrection::IsPowerOfTwo(Int_t i) const {
7d855b04 1656 /// Helperfunction: Check if integer is a power of 2
1657
1b923461 1658 Int_t j = 0;
1659 while( i > 0 ) { j += (i&1) ; i = (i>>1) ; }
1660 if ( j == 1 ) return(1) ; // True
1661 return(0) ; // False
1662}
1663
cf5b0aa0 1664
b1f0a2a5 1665AliExternalTrackParam * AliTPCCorrection::FitDistortedTrack(AliExternalTrackParam & trackIn, Double_t refX, Int_t dir, TTreeSRedirector * const pcstream){
7d855b04 1666 /// Fit the track parameters - without and with distortion
1667 /// 1. Space points in the TPC are simulated along the trajectory
1668 /// 2. Space points distorted
1669 /// 3. Fits the non distorted and distroted track to the reference plane at refX
1670 /// 4. For visualization and debugging purposes the space points and tracks can be stored in the tree - using the TTreeSRedirector functionality
1671 ///
1672 /// trackIn - input track parameters
1673 /// refX - reference X to fit the track
1674 /// dir - direction - out=1 or in=-1
1675 /// pcstream - debug streamer to check the results
1676 ///
1677 /// see AliExternalTrackParam.h documentation:
1678 /// track1.fP[0] - local y (rphi)
1679 /// track1.fP[1] - z
1680 /// track1.fP[2] - sinus of local inclination angle
1681 /// track1.fP[3] - tangent of deep angle
1682 /// track1.fP[4] - 1/pt
1b923461 1683
cf5b0aa0 1684 AliTPCROC * roc = AliTPCROC::Instance();
1685 const Int_t npoints0=roc->GetNRows(0)+roc->GetNRows(36);
1686 const Double_t kRTPC0 =roc->GetPadRowRadii(0,0);
1687 const Double_t kRTPC1 =roc->GetPadRowRadii(36,roc->GetNRows(36)-1);
7d855b04 1688 const Double_t kMaxSnp = 0.85;
cf5b0aa0 1689 const Double_t kSigmaY=0.1;
1690 const Double_t kSigmaZ=0.1;
ca58ed4e 1691 const Double_t kMaxR=500;
1692 const Double_t kMaxZ=500;
7d855b04 1693
cfe2c39a 1694 const Double_t kMaxZ0=220;
1695 const Double_t kZcut=3;
cf5b0aa0 1696 const Double_t kMass = TDatabasePDG::Instance()->GetParticle("pi+")->Mass();
ca58ed4e 1697 Int_t npoints1=0;
1698 Int_t npoints2=0;
cf5b0aa0 1699
7d855b04 1700 AliExternalTrackParam track(trackIn); //
cf5b0aa0 1701 // generate points
1702 AliTrackPointArray pointArray0(npoints0);
1703 AliTrackPointArray pointArray1(npoints0);
1704 Double_t xyz[3];
cfe2c39a 1705 if (!AliTrackerBase::PropagateTrackTo(&track,kRTPC0,kMass,5,kTRUE,kMaxSnp)) return 0;
cf5b0aa0 1706 //
1707 // simulate the track
1708 Int_t npoints=0;
2942f542 1709 Float_t covPoint[6]={0,0,0, static_cast<Float_t>(kSigmaY*kSigmaY),0,static_cast<Float_t>(kSigmaZ*kSigmaZ)}; //covariance at the local frame
cf5b0aa0 1710 for (Double_t radius=kRTPC0; radius<kRTPC1; radius++){
cfe2c39a 1711 if (!AliTrackerBase::PropagateTrackTo(&track,radius,kMass,5,kTRUE,kMaxSnp)) return 0;
cf5b0aa0 1712 track.GetXYZ(xyz);
cfe2c39a 1713 xyz[0]+=gRandom->Gaus(0,0.000005);
1714 xyz[1]+=gRandom->Gaus(0,0.000005);
1715 xyz[2]+=gRandom->Gaus(0,0.000005);
1716 if (TMath::Abs(track.GetZ())>kMaxZ0) continue;
46e89793 1717 if (TMath::Abs(track.GetX())<kRTPC0) continue;
1718 if (TMath::Abs(track.GetX())>kRTPC1) continue;
7d855b04 1719 AliTrackPoint pIn0; // space point
cf5b0aa0 1720 AliTrackPoint pIn1;
ffab0c37 1721 Int_t sector= (xyz[2]>0)? 0:18;
cf5b0aa0 1722 pointArray0.GetPoint(pIn0,npoints);
1723 pointArray1.GetPoint(pIn1,npoints);
1724 Double_t alpha = TMath::ATan2(xyz[1],xyz[0]);
2942f542 1725 Float_t distPoint[3]={static_cast<Float_t>(xyz[0]),static_cast<Float_t>(xyz[1]),static_cast<Float_t>(xyz[2])};
ffab0c37 1726 DistortPoint(distPoint, sector);
cf5b0aa0 1727 pIn0.SetXYZ(xyz[0], xyz[1],xyz[2]);
1728 pIn1.SetXYZ(distPoint[0], distPoint[1],distPoint[2]);
1729 //
1730 track.Rotate(alpha);
1731 AliTrackPoint prot0 = pIn0.Rotate(alpha); // rotate to the local frame - non distoted point
1732 AliTrackPoint prot1 = pIn1.Rotate(alpha); // rotate to the local frame - distorted point
1733 prot0.SetXYZ(prot0.GetX(),prot0.GetY(), prot0.GetZ(),covPoint);
1734 prot1.SetXYZ(prot1.GetX(),prot1.GetY(), prot1.GetZ(),covPoint);
1735 pIn0=prot0.Rotate(-alpha); // rotate back to global frame
1736 pIn1=prot1.Rotate(-alpha); // rotate back to global frame
7d855b04 1737 pointArray0.AddPoint(npoints, &pIn0);
cf5b0aa0 1738 pointArray1.AddPoint(npoints, &pIn1);
1739 npoints++;
1740 if (npoints>=npoints0) break;
1741 }
cfe2c39a 1742 if (npoints<npoints0/4.) return 0;
cf5b0aa0 1743 //
1744 // refit track
1745 //
1746 AliExternalTrackParam *track0=0;
1747 AliExternalTrackParam *track1=0;
1748 AliTrackPoint point1,point2,point3;
1749 if (dir==1) { //make seed inner
1750 pointArray0.GetPoint(point1,1);
cfe2c39a 1751 pointArray0.GetPoint(point2,11);
1752 pointArray0.GetPoint(point3,21);
cf5b0aa0 1753 }
1754 if (dir==-1){ //make seed outer
cfe2c39a 1755 pointArray0.GetPoint(point1,npoints-21);
1756 pointArray0.GetPoint(point2,npoints-11);
cf5b0aa0 1757 pointArray0.GetPoint(point3,npoints-1);
7d855b04 1758 }
46e89793 1759 if ((TMath::Abs(point1.GetX()-point3.GetX())+TMath::Abs(point1.GetY()-point3.GetY()))<10){
1760 printf("fit points not properly initialized\n");
1761 return 0;
1762 }
cf5b0aa0 1763 track0 = AliTrackerBase::MakeSeed(point1, point2, point3);
1764 track1 = AliTrackerBase::MakeSeed(point1, point2, point3);
cfe2c39a 1765 track0->ResetCovariance(10);
1766 track1->ResetCovariance(10);
1767 if (TMath::Abs(AliTrackerBase::GetBz())<0.01){
7d855b04 1768 ((Double_t*)track0->GetParameter())[4]= trackIn.GetParameter()[4];
cfe2c39a 1769 ((Double_t*)track1->GetParameter())[4]= trackIn.GetParameter()[4];
1770 }
cf5b0aa0 1771 for (Int_t jpoint=0; jpoint<npoints; jpoint++){
8b63d99c 1772 Int_t ipoint= (dir>0) ? jpoint: npoints-1-jpoint;
cf5b0aa0 1773 //
1774 AliTrackPoint pIn0;
1775 AliTrackPoint pIn1;
1776 pointArray0.GetPoint(pIn0,ipoint);
1777 pointArray1.GetPoint(pIn1,ipoint);
1778 AliTrackPoint prot0 = pIn0.Rotate(track0->GetAlpha()); // rotate to the local frame - non distoted point
1779 AliTrackPoint prot1 = pIn1.Rotate(track1->GetAlpha()); // rotate to the local frame - distorted point
46e89793 1780 if (TMath::Abs(prot0.GetX())<kRTPC0) continue;
1781 if (TMath::Abs(prot0.GetX())>kRTPC1) continue;
cf5b0aa0 1782 //
cfe2c39a 1783 if (!AliTrackerBase::PropagateTrackTo(track0,prot0.GetX(),kMass,5,kFALSE,kMaxSnp)) break;
1784 if (!AliTrackerBase::PropagateTrackTo(track1,prot0.GetX(),kMass,5,kFALSE,kMaxSnp)) break;
ca58ed4e 1785 if (TMath::Abs(track0->GetZ())>kMaxZ) break;
1786 if (TMath::Abs(track0->GetX())>kMaxR) break;
1787 if (TMath::Abs(track1->GetZ())>kMaxZ) break;
1788 if (TMath::Abs(track1->GetX())>kMaxR) break;
cfe2c39a 1789 if (dir>0 && track1->GetX()>refX) continue;
1790 if (dir<0 && track1->GetX()<refX) continue;
1791 if (TMath::Abs(track1->GetZ())<kZcut)continue;
8b63d99c 1792 track.GetXYZ(xyz); // distorted track also propagated to the same reference radius
cf5b0aa0 1793 //
1794 Double_t pointPos[2]={0,0};
1795 Double_t pointCov[3]={0,0,0};
1796 pointPos[0]=prot0.GetY();//local y
1797 pointPos[1]=prot0.GetZ();//local z
1798 pointCov[0]=prot0.GetCov()[3];//simay^2
1799 pointCov[1]=prot0.GetCov()[4];//sigmayz
1800 pointCov[2]=prot0.GetCov()[5];//sigmaz^2
ca58ed4e 1801 if (!track0->Update(pointPos,pointCov)) break;
cf5b0aa0 1802 //
7d855b04 1803 Double_t deltaX=prot1.GetX()-prot0.GetX(); // delta X
8b63d99c 1804 Double_t deltaYX=deltaX*TMath::Tan(TMath::ASin(track1->GetSnp())); // deltaY due delta X
1805 Double_t deltaZX=deltaX*track1->GetTgl(); // deltaZ due delta X
1806
0b736a46 1807 pointPos[0]=prot1.GetY()-deltaYX;//local y is sign correct? should be minus
1808 pointPos[1]=prot1.GetZ()-deltaZX;//local z is sign correct? should be minus
cf5b0aa0 1809 pointCov[0]=prot1.GetCov()[3];//simay^2
1810 pointCov[1]=prot1.GetCov()[4];//sigmayz
1811 pointCov[2]=prot1.GetCov()[5];//sigmaz^2
ca58ed4e 1812 if (!track1->Update(pointPos,pointCov)) break;
1813 npoints1++;
1814 npoints2++;
cf5b0aa0 1815 }
cfe2c39a 1816 if (npoints2<npoints/4.) return 0;
1817 AliTrackerBase::PropagateTrackTo(track0,refX,kMass,5.,kTRUE,kMaxSnp);
1818 AliTrackerBase::PropagateTrackTo(track0,refX,kMass,1.,kTRUE,kMaxSnp);
cf5b0aa0 1819 track1->Rotate(track0->GetAlpha());
cfe2c39a 1820 AliTrackerBase::PropagateTrackTo(track1,track0->GetX(),kMass,5.,kFALSE,kMaxSnp);
cf5b0aa0 1821
cad404e1 1822 if (pcstream) (*pcstream)<<Form("fitDistort%s",GetName())<<
cf5b0aa0 1823 "point0.="<<&pointArray0<< // points
1824 "point1.="<<&pointArray1<< // distorted points
1825 "trackIn.="<<&track<< // original track
1826 "track0.="<<track0<< // fitted track
1827 "track1.="<<track1<< // fitted distorted track
1828 "\n";
be67055b 1829 new(&trackIn) AliExternalTrackParam(*track0);
cf5b0aa0 1830 delete track0;
1831 return track1;
1832}
1833
1834
ffab0c37 1835
1836
1837
1838TTree* AliTPCCorrection::CreateDistortionTree(Double_t step){
7d855b04 1839 /// create the distortion tree on a mesh with granularity given by step
1840 /// return the tree with distortions at given position
1841 /// Map is created on the mesh with given step size
1842
ffab0c37 1843 TTreeSRedirector *pcstream = new TTreeSRedirector(Form("correction%s.root",GetName()));
1844 Float_t xyz[3];
1845 for (Double_t x= -250; x<250; x+=step){
1846 for (Double_t y= -250; y<250; y+=step){
1847 Double_t r = TMath::Sqrt(x*x+y*y);
1848 if (r<80) continue;
7d855b04 1849 if (r>250) continue;
ffab0c37 1850 for (Double_t z= -250; z<250; z+=step){
1851 Int_t roc=(z>0)?0:18;
1852 xyz[0]=x;
1853 xyz[1]=y;
1854 xyz[2]=z;
1855 Double_t phi = TMath::ATan2(y,x);
1856 DistortPoint(xyz,roc);
1857 Double_t r1 = TMath::Sqrt(xyz[0]*xyz[0]+xyz[1]*xyz[1]);
1858 Double_t phi1 = TMath::ATan2(xyz[1],xyz[0]);
1859 if ((phi1-phi)>TMath::Pi()) phi1-=TMath::Pi();
1860 if ((phi1-phi)<-TMath::Pi()) phi1+=TMath::Pi();
1861 Double_t dx = xyz[0]-x;
1862 Double_t dy = xyz[1]-y;
1863 Double_t dz = xyz[2]-z;
1864 Double_t dr=r1-r;
1865 Double_t drphi=(phi1-phi)*r;
1866 (*pcstream)<<"distortion"<<
7d855b04 1867 "x="<<x<< // original position
ffab0c37 1868 "y="<<y<<
1869 "z="<<z<<
1870 "r="<<r<<
7d855b04 1871 "phi="<<phi<<
ffab0c37 1872 "x1="<<xyz[0]<< // distorted position
1873 "y1="<<xyz[1]<<
1874 "z1="<<xyz[2]<<
1875 "r1="<<r1<<
1876 "phi1="<<phi1<<
1877 //
1878 "dx="<<dx<< // delta position
1879 "dy="<<dy<<
1880 "dz="<<dz<<
1881 "dr="<<dr<<
1882 "drphi="<<drphi<<
1883 "\n";
1884 }
7d855b04 1885 }
ffab0c37 1886 }
1887 delete pcstream;
1888 TFile f(Form("correction%s.root",GetName()));
1889 TTree * tree = (TTree*)f.Get("distortion");
1890 TTree * tree2= tree->CopyTree("1");
1891 tree2->SetName(Form("dist%s",GetName()));
1892 tree2->SetDirectory(0);
1893 delete tree;
1894 return tree2;
1895}
1896
1897
1898
be67055b 1899
46e89793 1900void AliTPCCorrection::MakeTrackDistortionTree(TTree *tinput, Int_t dtype, Int_t ptype, const TObjArray * corrArray, Int_t step, Int_t offset, Bool_t debug ){
7d855b04 1901 /// Make a fit tree:
1902 /// For each partial correction (specified in array) and given track topology (phi, theta, snp, refX)
1903 /// calculates partial distortions
1904 /// Partial distortion is stored in the resulting tree
1905 /// Output is storred in the file distortion_<dettype>_<partype>.root
1906 /// Partial distortion is stored with the name given by correction name
1907 ///
1908 /// Parameters of function:
1909 /// input - input tree
1910 /// dtype - distortion type 0 - ITSTPC, 1 -TPCTRD, 2 - TPCvertex , 3 - TPC-TOF, 4 - TPCTPC track crossing
1911 /// ppype - parameter type
1912 /// corrArray - array with partial corrections
1913 /// step - skipe entries - if 1 all entries processed - it is slow
1914 /// debug 0 if debug on also space points dumped - it is slow
1915
1916 const Double_t kMaxSnp = 0.85;
cfe2c39a 1917 const Double_t kcutSnp=0.25;
1918 const Double_t kcutTheta=1.;
1919 const Double_t kRadiusTPC=85;
7d855b04 1920 // AliTPCROC *tpcRoc =AliTPCROC::Instance();
cfe2c39a 1921 //
b322e06a 1922 const Double_t kMass = TDatabasePDG::Instance()->GetParticle("pi+")->Mass();
1923 // const Double_t kB2C=-0.299792458e-3;
7d855b04 1924 const Int_t kMinEntries=20;
cfe2c39a 1925 Double_t phi,theta, snp, mean,rms, entries,sector,dsec;
7d855b04 1926 Float_t refX;
46e89793 1927 Int_t run;
1928 tinput->SetBranchAddress("run",&run);
be67055b 1929 tinput->SetBranchAddress("theta",&theta);
1930 tinput->SetBranchAddress("phi", &phi);
1931 tinput->SetBranchAddress("snp",&snp);
1932 tinput->SetBranchAddress("mean",&mean);
1933 tinput->SetBranchAddress("rms",&rms);
1934 tinput->SetBranchAddress("entries",&entries);
cfe2c39a 1935 tinput->SetBranchAddress("sector",&sector);
1936 tinput->SetBranchAddress("dsec",&dsec);
1937 tinput->SetBranchAddress("refX",&refX);
46e89793 1938 TTreeSRedirector *pcstream = new TTreeSRedirector(Form("distortion%d_%d_%d.root",dtype,ptype,offset));
be67055b 1939 //
1940 Int_t nentries=tinput->GetEntries();
1941 Int_t ncorr=corrArray->GetEntries();
7f4cb119 1942 Double_t corrections[100]={0}; //
be67055b 1943 Double_t tPar[5];
1944 Double_t cov[15]={0,0,0,0,0,0,0,0,0,0,0,0,0,0};
be67055b 1945 Int_t dir=0;
cfe2c39a 1946 if (dtype==5 || dtype==6) dtype=4;
1947 if (dtype==0) { dir=-1;}
1948 if (dtype==1) { dir=1;}
1949 if (dtype==2) { dir=-1;}
1950 if (dtype==3) { dir=1;}
1951 if (dtype==4) { dir=-1;}
be67055b 1952 //
46e89793 1953 for (Int_t ientry=offset; ientry<nentries; ientry+=step){
be67055b 1954 tinput->GetEntry(ientry);
7f4cb119 1955 if (TMath::Abs(snp)>kMaxSnp) continue;
be67055b 1956 tPar[0]=0;
1957 tPar[1]=theta*refX;
cfe2c39a 1958 if (dtype==2) tPar[1]=theta*kRadiusTPC;
be67055b 1959 tPar[2]=snp;
1960 tPar[3]=theta;
4486a91f 1961 tPar[4]=(gRandom->Rndm()-0.5)*0.02; // should be calculated - non equal to 0
cfe2c39a 1962 if (dtype==4){
1963 // tracks crossing CE
1964 tPar[1]=0; // track at the CE
1965 //if (TMath::Abs(theta) <0.05) continue; // deep cross
1966 }
1967
1968 if (TMath::Abs(snp) >kcutSnp) continue;
1969 if (TMath::Abs(theta) >kcutTheta) continue;
1970 printf("%f\t%f\t%f\t%f\t%f\t%f\n",entries, sector,theta,snp, mean,rms);
8b63d99c 1971 Double_t bz=AliTrackerBase::GetBz();
cfe2c39a 1972 if (dtype !=4) { //exclude TPC - for TPC mainly non primary tracks
1973 if (dtype!=2 && TMath::Abs(bz)>0.1 ) tPar[4]=snp/(refX*bz*kB2C*2);
7d855b04 1974
cfe2c39a 1975 if (dtype==2 && TMath::Abs(bz)>0.1 ) {
1976 tPar[4]=snp/(kRadiusTPC*bz*kB2C*2);//
1977 // snp at the TPC inner radius in case the vertex match used
1978 }
1979 }
1980 //
4486a91f 1981 tPar[4]+=(gRandom->Rndm()-0.5)*0.02;
7f4cb119 1982 AliExternalTrackParam track(refX,phi,tPar,cov);
1983 Double_t xyz[3];
1984 track.GetXYZ(xyz);
1985 Int_t id=0;
46e89793 1986 Double_t pt=1./tPar[4];
7f4cb119 1987 Double_t dRrec=0; // dummy value - needed for points - e.g for laser
cfe2c39a 1988 //if (ptype==4 &&bz<0) mean*=-1; // interpret as curvature -- COMMENTED out - in lookup signed 1/pt used
46e89793 1989 Double_t refXD=refX;
be67055b 1990 (*pcstream)<<"fit"<<
46e89793 1991 "run="<<run<< // run number
8b63d99c 1992 "bz="<<bz<< // magnetic filed used
be67055b 1993 "dtype="<<dtype<< // detector match type
1994 "ptype="<<ptype<< // parameter type
1995 "theta="<<theta<< // theta
7d855b04 1996 "phi="<<phi<< // phi
be67055b 1997 "snp="<<snp<< // snp
1998 "mean="<<mean<< // mean dist value
1999 "rms="<<rms<< // rms
cfe2c39a 2000 "sector="<<sector<<
2001 "dsec="<<dsec<<
46e89793 2002 "refX="<<refXD<< // referece X as double
7f4cb119 2003 "gx="<<xyz[0]<< // global position at reference
2004 "gy="<<xyz[1]<< // global position at reference
7d855b04 2005 "gz="<<xyz[2]<< // global position at reference
7f4cb119 2006 "dRrec="<<dRrec<< // delta Radius in reconstruction
46e89793 2007 "pt="<<pt<< // pt
7f4cb119 2008 "id="<<id<< // track id
be67055b 2009 "entries="<<entries;// number of entries in bin
2010 //
cfe2c39a 2011 Bool_t isOK=kTRUE;
46e89793 2012 if (entries<kMinEntries) isOK=kFALSE;
2013 //
cfe2c39a 2014 if (dtype!=4) for (Int_t icorr=0; icorr<ncorr; icorr++) {
be67055b 2015 AliTPCCorrection *corr = (AliTPCCorrection*)corrArray->At(icorr);
2016 corrections[icorr]=0;
2017 if (entries>kMinEntries){
2018 AliExternalTrackParam trackIn(refX,phi,tPar,cov);
2019 AliExternalTrackParam *trackOut = 0;
2020 if (debug) trackOut=corr->FitDistortedTrack(trackIn, refX, dir,pcstream);
2021 if (!debug) trackOut=corr->FitDistortedTrack(trackIn, refX, dir,0);
cfe2c39a 2022 if (dtype==0) {dir= -1;}
2023 if (dtype==1) {dir= 1;}
2024 if (dtype==2) {dir= -1;}
2025 if (dtype==3) {dir= 1;}
b1f0a2a5 2026 //
7f4cb119 2027 if (trackOut){
cfe2c39a 2028 if (!AliTrackerBase::PropagateTrackTo(&trackIn,refX,kMass,5,kTRUE,kMaxSnp)) isOK=kFALSE;
2029 if (!trackOut->Rotate(trackIn.GetAlpha())) isOK=kFALSE;
2030 if (!AliTrackerBase::PropagateTrackTo(trackOut,trackIn.GetX(),kMass,5,kFALSE,kMaxSnp)) isOK=kFALSE;
2031 // trackOut->PropagateTo(trackIn.GetX(),AliTrackerBase::GetBz());
7d855b04 2032 //
7f4cb119 2033 corrections[icorr]= trackOut->GetParameter()[ptype]-trackIn.GetParameter()[ptype];
7d855b04 2034 delete trackOut;
7f4cb119 2035 }else{
2036 corrections[icorr]=0;
cfe2c39a 2037 isOK=kFALSE;
7f4cb119 2038 }
cfe2c39a 2039 //if (ptype==4 &&bz<0) corrections[icorr]*=-1; // interpret as curvature - commented out
7d855b04 2040 }
be67055b 2041 (*pcstream)<<"fit"<<
46e89793 2042 Form("%s=",corr->GetName())<<corrections[icorr]; // dump correction value
be67055b 2043 }
7d855b04 2044
cfe2c39a 2045 if (dtype==4) for (Int_t icorr=0; icorr<ncorr; icorr++) {
2046 //
2047 // special case of the TPC tracks crossing the CE
2048 //
2049 AliTPCCorrection *corr = (AliTPCCorrection*)corrArray->At(icorr);
2050 corrections[icorr]=0;
2051 if (entries>kMinEntries){
46e89793 2052 AliExternalTrackParam trackIn0(refX,phi,tPar,cov); //Outer - direction to vertex
7d855b04 2053 AliExternalTrackParam trackIn1(refX,phi,tPar,cov); //Inner - direction magnet
cfe2c39a 2054 AliExternalTrackParam *trackOut0 = 0;
2055 AliExternalTrackParam *trackOut1 = 0;
2056 //
2057 if (debug) trackOut0=corr->FitDistortedTrack(trackIn0, refX, dir,pcstream);
2058 if (!debug) trackOut0=corr->FitDistortedTrack(trackIn0, refX, dir,0);
2059 if (debug) trackOut1=corr->FitDistortedTrack(trackIn1, refX, -dir,pcstream);
2060 if (!debug) trackOut1=corr->FitDistortedTrack(trackIn1, refX, -dir,0);
2061 //
2062 if (trackOut0 && trackOut1){
2063 if (!AliTrackerBase::PropagateTrackTo(&trackIn0,refX,kMass,5,kTRUE,kMaxSnp)) isOK=kFALSE;
2064 if (!AliTrackerBase::PropagateTrackTo(&trackIn0,refX,kMass,1,kFALSE,kMaxSnp)) isOK=kFALSE;
2065 if (!trackOut0->Rotate(trackIn0.GetAlpha())) isOK=kFALSE;
2066 if (!AliTrackerBase::PropagateTrackTo(trackOut0,trackIn0.GetX(),kMass,5,kFALSE,kMaxSnp)) isOK=kFALSE;
2067 //
2068 if (!AliTrackerBase::PropagateTrackTo(&trackIn1,refX,kMass,5,kTRUE,kMaxSnp)) isOK=kFALSE;
2069 if (!trackIn1.Rotate(trackIn0.GetAlpha())) isOK=kFALSE;
2070 if (!AliTrackerBase::PropagateTrackTo(&trackIn1,trackIn0.GetX(),kMass,1,kFALSE,kMaxSnp)) isOK=kFALSE;
7d855b04 2071 if (!trackOut1->Rotate(trackIn1.GetAlpha())) isOK=kFALSE;
cfe2c39a 2072 if (!AliTrackerBase::PropagateTrackTo(trackOut1,trackIn1.GetX(),kMass,5,kFALSE,kMaxSnp)) isOK=kFALSE;
2073 //
2074 corrections[icorr] = (trackOut0->GetParameter()[ptype]-trackIn0.GetParameter()[ptype]);
2075 corrections[icorr]-= (trackOut1->GetParameter()[ptype]-trackIn1.GetParameter()[ptype]);
46e89793 2076 if (isOK)
2077 if ((TMath::Abs(trackOut0->GetX()-trackOut1->GetX())>0.1)||
2078 (TMath::Abs(trackOut0->GetX()-trackIn1.GetX())>0.1)||
2079 (TMath::Abs(trackOut0->GetAlpha()-trackOut1->GetAlpha())>0.00001)||
2080 (TMath::Abs(trackOut0->GetAlpha()-trackIn1.GetAlpha())>0.00001)||
2081 (TMath::Abs(trackIn0.GetTgl()-trackIn1.GetTgl())>0.0001)||
2082 (TMath::Abs(trackIn0.GetSnp()-trackIn1.GetSnp())>0.0001)
2083 ){
2084 isOK=kFALSE;
7d855b04 2085 }
2086 delete trackOut0;
2087 delete trackOut1;
cfe2c39a 2088 }else{
2089 corrections[icorr]=0;
2090 isOK=kFALSE;
2091 }
2092 //
2093 //if (ptype==4 &&bz<0) corrections[icorr]*=-1; // interpret as curvature - commented out no in lookup
7d855b04 2094 }
cfe2c39a 2095 (*pcstream)<<"fit"<<
46e89793 2096 Form("%s=",corr->GetName())<<corrections[icorr]; // dump correction value
cfe2c39a 2097 }
2098 //
2099 (*pcstream)<<"fit"<<"isOK="<<isOK<<"\n";
be67055b 2100 }
cfe2c39a 2101
2102
be67055b 2103 delete pcstream;
2104}
2105
2106
2107
46e89793 2108void AliTPCCorrection::MakeSectorDistortionTree(TTree *tinput, Int_t dtype, Int_t ptype, const TObjArray * corrArray, Int_t step, Int_t offset, Bool_t debug ){
7d855b04 2109 /// Make a fit tree:
2110 /// For each partial correction (specified in array) and given track topology (phi, theta, snp, refX)
2111 /// calculates partial distortions
2112 /// Partial distortion is stored in the resulting tree
2113 /// Output is storred in the file distortion_<dettype>_<partype>.root
2114 /// Partial distortion is stored with the name given by correction name
2115 ///
2116 /// Parameters of function:
2117 /// input - input tree
2118 /// dtype - distortion type 10 - IROC-OROC
2119 /// ppype - parameter type
2120 /// corrArray - array with partial corrections
2121 /// step - skipe entries - if 1 all entries processed - it is slow
2122 /// debug 0 if debug on also space points dumped - it is slow
2123
2124 const Double_t kMaxSnp = 0.8;
2125 const Int_t kMinEntries=200;
2126 // AliTPCROC *tpcRoc =AliTPCROC::Instance();
46e89793 2127 //
2128 const Double_t kMass = TDatabasePDG::Instance()->GetParticle("pi+")->Mass();
2129 // const Double_t kB2C=-0.299792458e-3;
2130 Double_t phi,theta, snp, mean,rms, entries,sector,dsec,globalZ;
2131 Int_t isec1, isec0;
2132 Double_t refXD;
2133 Float_t refX;
2134 Int_t run;
2135 tinput->SetBranchAddress("run",&run);
2136 tinput->SetBranchAddress("theta",&theta);
2137 tinput->SetBranchAddress("phi", &phi);
2138 tinput->SetBranchAddress("snp",&snp);
2139 tinput->SetBranchAddress("mean",&mean);
2140 tinput->SetBranchAddress("rms",&rms);
2141 tinput->SetBranchAddress("entries",&entries);
2142 tinput->SetBranchAddress("sector",&sector);
2143 tinput->SetBranchAddress("dsec",&dsec);
2144 tinput->SetBranchAddress("refX",&refXD);
2145 tinput->SetBranchAddress("z",&globalZ);
2146 tinput->SetBranchAddress("isec0",&isec0);
2147 tinput->SetBranchAddress("isec1",&isec1);
2148 TTreeSRedirector *pcstream = new TTreeSRedirector(Form("distortionSector%d_%d_%d.root",dtype,ptype,offset));
2149 //
2150 Int_t nentries=tinput->GetEntries();
2151 Int_t ncorr=corrArray->GetEntries();
2152 Double_t corrections[100]={0}; //
2153 Double_t tPar[5];
2154 Double_t cov[15]={0,0,0,0,0,0,0,0,0,0,0,0,0,0};
2155 Int_t dir=0;
2156 //
2157 for (Int_t ientry=offset; ientry<nentries; ientry+=step){
2158 tinput->GetEntry(ientry);
2159 refX=refXD;
2160 Int_t id=-1;
2161 if (TMath::Abs(TMath::Abs(isec0%18)-TMath::Abs(isec1%18))==0) id=1; // IROC-OROC - opposite side
2162 if (TMath::Abs(TMath::Abs(isec0%36)-TMath::Abs(isec1%36))==0) id=2; // IROC-OROC - same side
2163 if (dtype==10 && id==-1) continue;
2164 //
2165 dir=-1;
2166 tPar[0]=0;
2167 tPar[1]=globalZ;
2168 tPar[2]=snp;
2169 tPar[3]=theta;
2170 tPar[4]=(gRandom->Rndm()-0.1)*0.2; //
2171 Double_t pt=1./tPar[4];
2172 //
2173 printf("%f\t%f\t%f\t%f\t%f\t%f\n",entries, sector,theta,snp, mean,rms);
2174 Double_t bz=AliTrackerBase::GetBz();
7d855b04 2175 AliExternalTrackParam track(refX,phi,tPar,cov);
46e89793 2176 Double_t xyz[3],xyzIn[3],xyzOut[3];
2177 track.GetXYZ(xyz);
7d855b04 2178 track.GetXYZAt(85,bz,xyzIn);
2179 track.GetXYZAt(245,bz,xyzOut);
46e89793 2180 Double_t phiIn = TMath::ATan2(xyzIn[1],xyzIn[0]);
2181 Double_t phiOut = TMath::ATan2(xyzOut[1],xyzOut[0]);
2182 Double_t phiRef = TMath::ATan2(xyz[1],xyz[0]);
2183 Int_t sectorRef = TMath::Nint(9.*phiRef/TMath::Pi()-0.5);
2184 Int_t sectorIn = TMath::Nint(9.*phiIn/TMath::Pi()-0.5);
2185 Int_t sectorOut = TMath::Nint(9.*phiOut/TMath::Pi()-0.5);
2186 //
7d855b04 2187 Bool_t isOK=kTRUE;
46e89793 2188 if (sectorIn!=sectorOut) isOK=kFALSE; // requironment - cluster in the same sector
2189 if (sectorIn!=sectorRef) isOK=kFALSE; // requironment - cluster in the same sector
2190 if (entries<kMinEntries/(1+TMath::Abs(globalZ/100.))) isOK=kFALSE; // requironment - minimal amount of tracks in bin
2191 // Do downscale
2192 if (TMath::Abs(theta)>1) isOK=kFALSE;
2193 //
2194 Double_t dRrec=0; // dummy value - needed for points - e.g for laser
2195 //
2196 (*pcstream)<<"fit"<<
2197 "run="<<run<< //run
2198 "bz="<<bz<< // magnetic filed used
2199 "dtype="<<dtype<< // detector match type
2200 "ptype="<<ptype<< // parameter type
2201 "theta="<<theta<< // theta
7d855b04 2202 "phi="<<phi<< // phi
46e89793 2203 "snp="<<snp<< // snp
2204 "mean="<<mean<< // mean dist value
2205 "rms="<<rms<< // rms
2206 "sector="<<sector<<
2207 "dsec="<<dsec<<
2208 "refX="<<refXD<< // referece X
2209 "gx="<<xyz[0]<< // global position at reference
2210 "gy="<<xyz[1]<< // global position at reference
7d855b04 2211 "gz="<<xyz[2]<< // global position at reference
46e89793 2212 "dRrec="<<dRrec<< // delta Radius in reconstruction
2213 "pt="<<pt<< //pt
2214 "id="<<id<< // track id
2215 "entries="<<entries;// number of entries in bin
2216 //
2217 AliExternalTrackParam *trackOut0 = 0;
2218 AliExternalTrackParam *trackOut1 = 0;
2219 AliExternalTrackParam *ptrackIn0 = 0;
2220 AliExternalTrackParam *ptrackIn1 = 0;
2221
2222 for (Int_t icorr=0; icorr<ncorr; icorr++) {
2223 //
2224 // special case of the TPC tracks crossing the CE
2225 //
2226 AliTPCCorrection *corr = (AliTPCCorrection*)corrArray->At(icorr);
2227 corrections[icorr]=0;
2228 if (entries>kMinEntries &&isOK){
2229 AliExternalTrackParam trackIn0(refX,phi,tPar,cov);
2230 AliExternalTrackParam trackIn1(refX,phi,tPar,cov);
2231 ptrackIn1=&trackIn0;
2232 ptrackIn0=&trackIn1;
2233 //
2234 if (debug) trackOut0=corr->FitDistortedTrack(trackIn0, refX, dir,pcstream);
2235 if (!debug) trackOut0=corr->FitDistortedTrack(trackIn0, refX, dir,0);
2236 if (debug) trackOut1=corr->FitDistortedTrack(trackIn1, refX, -dir,pcstream);
2237 if (!debug) trackOut1=corr->FitDistortedTrack(trackIn1, refX, -dir,0);
2238 //
2239 if (trackOut0 && trackOut1){
2240 //
2241 if (!AliTrackerBase::PropagateTrackTo(&trackIn0,refX,kMass,1,kTRUE,kMaxSnp)) isOK=kFALSE;
2242 if (!AliTrackerBase::PropagateTrackTo(&trackIn0,refX,kMass,1,kFALSE,kMaxSnp)) isOK=kFALSE;
2243 // rotate all tracks to the same frame
2244 if (!trackOut0->Rotate(trackIn0.GetAlpha())) isOK=kFALSE;
2245 if (!trackIn1.Rotate(trackIn0.GetAlpha())) isOK=kFALSE;
7d855b04 2246 if (!trackOut1->Rotate(trackIn0.GetAlpha())) isOK=kFALSE;
46e89793 2247 //
2248 if (!AliTrackerBase::PropagateTrackTo(trackOut0,refX,kMass,1,kFALSE,kMaxSnp)) isOK=kFALSE;
2249 if (!AliTrackerBase::PropagateTrackTo(&trackIn1,refX,kMass,1,kFALSE,kMaxSnp)) isOK=kFALSE;
2250 if (!AliTrackerBase::PropagateTrackTo(trackOut1,refX,kMass,1,kFALSE,kMaxSnp)) isOK=kFALSE;
2251 //
2252 corrections[icorr] = (trackOut0->GetParameter()[ptype]-trackIn0.GetParameter()[ptype]);
2253 corrections[icorr]-= (trackOut1->GetParameter()[ptype]-trackIn1.GetParameter()[ptype]);
2254 (*pcstream)<<"fitDebug"<< // just to debug the correction
2255 "mean="<<mean<<
2256 "pIn0.="<<ptrackIn0<<
2257 "pIn1.="<<ptrackIn1<<
2258 "pOut0.="<<trackOut0<<
2259 "pOut1.="<<trackOut1<<
2260 "refX="<<refXD<<
2261 "\n";
7d855b04 2262 delete trackOut0;
2263 delete trackOut1;
46e89793 2264 }else{
2265 corrections[icorr]=0;
2266 isOK=kFALSE;
2267 }
7d855b04 2268 }
46e89793 2269 (*pcstream)<<"fit"<<
2270 Form("%s=",corr->GetName())<<corrections[icorr]; // dump correction value
2271 }
2272 //
2273 (*pcstream)<<"fit"<<"isOK="<<isOK<<"\n";
2274 }
2275 delete pcstream;
2276}
2277
2278
2279
2280void AliTPCCorrection::MakeLaserDistortionTreeOld(TTree* tree, TObjArray *corrArray, Int_t itype){
7d855b04 2281 /// Make a laser fit tree for global minimization
2282
7f4cb119 2283 const Double_t cutErrY=0.1;
2284 const Double_t cutErrZ=0.1;
2285 const Double_t kEpsilon=0.00000001;
46e89793 2286 const Double_t kMaxDist=1.; // max distance - space correction
2287 const Double_t kMaxRMS=0.05; // max distance -between point and local mean
7f4cb119 2288 TVectorD *vecdY=0;
2289 TVectorD *vecdZ=0;
2290 TVectorD *veceY=0;
2291 TVectorD *veceZ=0;
2292 AliTPCLaserTrack *ltr=0;
2293 AliTPCLaserTrack::LoadTracks();
2294 tree->SetBranchAddress("dY.",&vecdY);
2295 tree->SetBranchAddress("dZ.",&vecdZ);
2296 tree->SetBranchAddress("eY.",&veceY);
2297 tree->SetBranchAddress("eZ.",&veceZ);
2298 tree->SetBranchAddress("LTr.",&ltr);
2299 Int_t entries= tree->GetEntries();
cfe2c39a 2300 TTreeSRedirector *pcstream= new TTreeSRedirector("distortionLaser_0.root");
7f4cb119 2301 Double_t bz=AliTrackerBase::GetBz();
7d855b04 2302 //
7f4cb119 2303
2304 for (Int_t ientry=0; ientry<entries; ientry++){
2305 tree->GetEntry(ientry);
2306 if (!ltr->GetVecGX()){
2307 ltr->UpdatePoints();
2308 }
2309 TVectorD * delta= (itype==0)? vecdY:vecdZ;
2310 TVectorD * err= (itype==0)? veceY:veceZ;
46e89793 2311 TLinearFitter fitter(2,"pol1");
2312 for (Int_t iter=0; iter<2; iter++){
2313 Double_t kfit0=0, kfit1=0;
2314 Int_t npoints=fitter.GetNpoints();
2315 if (npoints>80){
2316 fitter.Eval();
2317 kfit0=fitter.GetParameter(0);
2318 kfit1=fitter.GetParameter(1);
2319 }
2320 for (Int_t irow=0; irow<159; irow++){
2321 Bool_t isOK=kTRUE;
2322 Int_t isOKF=0;
2323 Int_t nentries = 1000;
2324 if (veceY->GetMatrixArray()[irow]>cutErrY||veceZ->GetMatrixArray()[irow]>cutErrZ) nentries=0;
2325 if (veceY->GetMatrixArray()[irow]<kEpsilon||veceZ->GetMatrixArray()[irow]<kEpsilon) nentries=0;
2326 Int_t dtype=5;
2327 Double_t array[10];
2328 Int_t first3=TMath::Max(irow-3,0);
2329 Int_t last3 =TMath::Min(irow+3,159);
2330 Int_t counter=0;
2331 if ((*ltr->GetVecSec())[irow]>=0 && err) {
2332 for (Int_t jrow=first3; jrow<=last3; jrow++){
2333 if ((*ltr->GetVecSec())[irow]!= (*ltr->GetVecSec())[jrow]) continue;
2334 if ((*err)[jrow]<kEpsilon) continue;
2335 array[counter]=(*delta)[jrow];
2336 counter++;
2337 }
7d855b04 2338 }
46e89793 2339 Double_t rms3 = 0;
2340 Double_t mean3 = 0;
2341 if (counter>2){
2342 rms3 = TMath::RMS(counter,array);
2343 mean3 = TMath::Mean(counter,array);
2344 }else{
2345 isOK=kFALSE;
2346 }
2347 Double_t phi =(*ltr->GetVecPhi())[irow];
2348 Double_t theta =ltr->GetTgl();
2349 Double_t mean=delta->GetMatrixArray()[irow];
2350 Double_t gx=0,gy=0,gz=0;
2351 Double_t snp = (*ltr->GetVecP2())[irow];
2352 Double_t dRrec=0;
2353 // Double_t rms = err->GetMatrixArray()[irow];
cfe2c39a 2354 //
46e89793 2355 gx = (*ltr->GetVecGX())[irow];
2356 gy = (*ltr->GetVecGY())[irow];
2357 gz = (*ltr->GetVecGZ())[irow];
2358 //
2359 // get delta R used in reconstruction
7d855b04 2360 AliTPCcalibDB* calib=AliTPCcalibDB::Instance();
46e89793 2361 AliTPCCorrection * correction = calib->GetTPCComposedCorrection(AliTrackerBase::GetBz());
2362 // const AliTPCRecoParam * recoParam = calib->GetTransform()->GetCurrentRecoParam();
2363 //Double_t xyz0[3]={gx,gy,gz};
2364 Double_t oldR=TMath::Sqrt(gx*gx+gy*gy);
7d855b04 2365 Double_t fphi = TMath::ATan2(gy,gx);
46e89793 2366 Double_t fsector = 9.*fphi/TMath::Pi();
2367 if (fsector<0) fsector+=18;
2368 Double_t dsec = fsector-Int_t(fsector)-0.5;
2369 Double_t refX=0;
2370 Int_t id= ltr->GetId();
2371 Double_t pt=0;
2372 //
2373 if (1 && oldR>1) {
2942f542 2374 Float_t xyz1[3]={static_cast<Float_t>(gx),static_cast<Float_t>(gy),static_cast<Float_t>(gz)};
46e89793 2375 Int_t sector=(gz>0)?0:18;
2376 correction->CorrectPoint(xyz1, sector);
2377 refX=TMath::Sqrt(xyz1[0]*xyz1[0]+xyz1[1]*xyz1[1]);
2378 dRrec=oldR-refX;
7d855b04 2379 }
46e89793 2380 if (TMath::Abs(rms3)>kMaxRMS) isOK=kFALSE;
2381 if (TMath::Abs(mean-mean3)>kMaxRMS) isOK=kFALSE;
7d855b04 2382 if (counter<4) isOK=kFALSE;
2383 if (npoints<90) isOK=kFALSE;
46e89793 2384 if (isOK){
2385 fitter.AddPoint(&refX,mean);
7f4cb119 2386 }
46e89793 2387 Double_t deltaF=kfit0+kfit1*refX;
2388 if (iter==1){
2389 (*pcstream)<<"fitFull"<< // dumpe also intermediate results
2390 "bz="<<bz<< // magnetic filed used
2391 "dtype="<<dtype<< // detector match type
2392 "ptype="<<itype<< // parameter type
2393 "theta="<<theta<< // theta
7d855b04 2394 "phi="<<phi<< // phi
46e89793 2395 "snp="<<snp<< // snp
2396 "mean="<<mean3<< // mean dist value
2397 "rms="<<rms3<< // rms
2398 "deltaF="<<deltaF<<
2399 "npoints="<<npoints<< //number of points
2400 "mean3="<<mean3<< // mean dist value
2401 "rms3="<<rms3<< // rms
2402 "counter="<<counter<<
2403 "sector="<<fsector<<
2404 "dsec="<<dsec<<
2405 //
2406 "refX="<<refX<< // reference radius
2407 "gx="<<gx<< // global position
2408 "gy="<<gy<< // global position
2409 "gz="<<gz<< // global position
2410 "dRrec="<<dRrec<< // delta Radius in reconstruction
7d855b04 2411 "id="<<id<< //bundle
46e89793 2412 "entries="<<nentries<<// number of entries in bin
2413 "\n";
2414 }
2415 if (iter==1) (*pcstream)<<"fit"<< // dump valus for fit
2416 "bz="<<bz<< // magnetic filed used
2417 "dtype="<<dtype<< // detector match type
2418 "ptype="<<itype<< // parameter type
2419 "theta="<<theta<< // theta
7d855b04 2420 "phi="<<phi<< // phi
46e89793 2421 "snp="<<snp<< // snp
2422 "mean="<<mean3<< // mean dist value
2423 "rms="<<rms3<< // rms
2424 "sector="<<fsector<<
2425 "dsec="<<dsec<<
2426 //
2427 "refX="<<refX<< // reference radius
2428 "gx="<<gx<< // global position
2429 "gy="<<gy<< // global position
2430 "gz="<<gz<< // global position
2431 "dRrec="<<dRrec<< // delta Radius in reconstruction
2432 "pt="<<pt<< //pt
7d855b04 2433 "id="<<id<< //bundle
46e89793 2434 "entries="<<nentries;// number of entries in bin
2435 //
7d855b04 2436 //
46e89793 2437 Double_t ky = TMath::Tan(TMath::ASin(snp));
2438 Int_t ncorr = corrArray->GetEntries();
2439 Double_t r0 = TMath::Sqrt(gx*gx+gy*gy);
2440 Double_t phi0 = TMath::ATan2(gy,gx);
2441 Double_t distortions[1000]={0};
2442 Double_t distortionsR[1000]={0};
2443 if (iter==1){
2444 for (Int_t icorr=0; icorr<ncorr; icorr++) {
2445 AliTPCCorrection *corr = (AliTPCCorrection*)corrArray->At(icorr);
7d855b04 2446 Float_t distPoint[3]={static_cast<Float_t>(gx),static_cast<Float_t>(gy),static_cast<Float_t>(gz)};
46e89793 2447 Int_t sector= (gz>0)? 0:18;
2448 if (r0>80){
2449 corr->DistortPoint(distPoint, sector);
2450 }
2451 // Double_t value=distPoint[2]-gz;
2452 if (itype==0 && r0>1){
2453 Double_t r1 = TMath::Sqrt(distPoint[0]*distPoint[0]+distPoint[1]*distPoint[1]);
2454 Double_t phi1 = TMath::ATan2(distPoint[1],distPoint[0]);
2455 Double_t drphi= r0*(phi1-phi0);
2456 Double_t dr = r1-r0;
2457 distortions[icorr] = drphi-ky*dr;
2458 distortionsR[icorr] = dr;
2459 }
2460 if (TMath::Abs(distortions[icorr])>kMaxDist) {isOKF=icorr+1; isOK=kFALSE; }
2461 if (TMath::Abs(distortionsR[icorr])>kMaxDist) {isOKF=icorr+1; isOK=kFALSE;}
2462 (*pcstream)<<"fit"<<
2463 Form("%s=",corr->GetName())<<distortions[icorr]; // dump correction value
2464 }
2465 (*pcstream)<<"fit"<<"isOK="<<isOK<<"\n";
7f4cb119 2466 }
7f4cb119 2467 }
7f4cb119 2468 }
2469 }
2470 delete pcstream;
2471}
2472
2473
be67055b 2474
97d17739 2475void AliTPCCorrection::MakeDistortionMap(THnSparse * his0, TTreeSRedirector * const pcstream, const char* hname, Int_t run, Float_t refX, Int_t type, Int_t integ){
7d855b04 2476 /// make a distortion map out ou fthe residual histogram
2477 /// Results are written to the debug streamer - pcstream
2478 /// Parameters:
2479 /// his0 - input (4D) residual histogram
2480 /// pcstream - file to write the tree
2481 /// run - run number
2482 /// refX - track matching reference X
2483 /// type - 0- y 1-z,2 -snp, 3-theta, 4=1/pt
2484 /// THnSparse axes:
2485 /// OBJ: TAxis #Delta #Delta
2486 /// OBJ: TAxis tanTheta tan(#Theta)
2487 /// OBJ: TAxis phi #phi
2488 /// OBJ: TAxis snp snp
cfe2c39a 2489
2490 // marian.ivanov@cern.ch
2491 const Int_t kMinEntries=10;
2492 Double_t bz=AliTrackerBase::GetBz();
2493 Int_t idim[4]={0,1,2,3};
2494 //
2495 //
2496 //
2497 Int_t nbins3=his0->GetAxis(3)->GetNbins();
2498 Int_t first3=his0->GetAxis(3)->GetFirst();
2499 Int_t last3 =his0->GetAxis(3)->GetLast();
2500 //
2501 for (Int_t ibin3=first3; ibin3<last3; ibin3+=1){ // axis 3 - local angle
97d17739 2502 his0->GetAxis(3)->SetRange(TMath::Max(ibin3-integ,1),TMath::Min(ibin3+integ,nbins3));
cfe2c39a 2503 Double_t x3= his0->GetAxis(3)->GetBinCenter(ibin3);
2504 THnSparse * his3= his0->Projection(3,idim); //projected histogram according selection 3
2505 //
2506 Int_t nbins2 = his3->GetAxis(2)->GetNbins();
2507 Int_t first2 = his3->GetAxis(2)->GetFirst();
2508 Int_t last2 = his3->GetAxis(2)->GetLast();
2509 //
2510 for (Int_t ibin2=first2; ibin2<last2; ibin2+=1){ // axis 2 - phi
97d17739 2511 his3->GetAxis(2)->SetRange(TMath::Max(ibin2-integ,1),TMath::Min(ibin2+integ,nbins2));
cfe2c39a 2512 Double_t x2= his3->GetAxis(2)->GetBinCenter(ibin2);
2513 THnSparse * his2= his3->Projection(2,idim); //projected histogram according selection 2
2514 Int_t nbins1 = his2->GetAxis(1)->GetNbins();
2515 Int_t first1 = his2->GetAxis(1)->GetFirst();
2516 Int_t last1 = his2->GetAxis(1)->GetLast();
2517 for (Int_t ibin1=first1; ibin1<last1; ibin1++){ //axis 1 - theta
2518 //
2519 Double_t x1= his2->GetAxis(1)->GetBinCenter(ibin1);
2520 his2->GetAxis(1)->SetRange(TMath::Max(ibin1-1,1),TMath::Min(ibin1+1,nbins1));
2521 if (TMath::Abs(x1)<0.1){
2522 if (x1<0) his2->GetAxis(1)->SetRange(TMath::Max(ibin1-1,1),TMath::Min(ibin1,nbins1));
2523 if (x1>0) his2->GetAxis(1)->SetRange(TMath::Max(ibin1,1),TMath::Min(ibin1+1,nbins1));
2524 }
2525 if (TMath::Abs(x1)<0.06){
2526 his2->GetAxis(1)->SetRange(TMath::Max(ibin1,1),TMath::Min(ibin1,nbins1));
2527 }
2528 TH1 * hisDelta = his2->Projection(0);
2529 //
2530 Double_t entries = hisDelta->GetEntries();
2531 Double_t mean=0, rms=0;
2532 if (entries>kMinEntries){
7d855b04 2533 mean = hisDelta->GetMean();
2534 rms = hisDelta->GetRMS();
cfe2c39a 2535 }
2536 Double_t sector = 9.*x2/TMath::Pi();
2537 if (sector<0) sector+=18;
2538 Double_t dsec = sector-Int_t(sector)-0.5;
2539 Double_t z=refX*x1;
2540 (*pcstream)<<hname<<
2541 "run="<<run<<
2542 "bz="<<bz<<
2543 "theta="<<x1<<
2544 "phi="<<x2<<
2545 "z="<<z<< // dummy z
2546 "snp="<<x3<<
2547 "entries="<<entries<<
2548 "mean="<<mean<<
2549 "rms="<<rms<<
2550 "refX="<<refX<< // track matching refernce plane
2551 "type="<<type<< //
2552 "sector="<<sector<<
2553 "dsec="<<dsec<<
2554 "\n";
2555 delete hisDelta;
02cd5ade 2556 //printf("%f\t%f\t%f\t%f\t%f\n",x3,x2,x1, entries,mean);
cfe2c39a 2557 }
2558 delete his2;
2559 }
2560 delete his3;
2561 }
2562}
2563
2564
2565
2566
2567void AliTPCCorrection::MakeDistortionMapCosmic(THnSparse * hisInput, TTreeSRedirector * const pcstream, const char* hname, Int_t run, Float_t refX, Int_t type){
7d855b04 2568 /// make a distortion map out ou fthe residual histogram
2569 /// Results are written to the debug streamer - pcstream
2570 /// Parameters:
2571 /// his0 - input (4D) residual histogram
2572 /// pcstream - file to write the tree
2573 /// run - run number
2574 /// refX - track matching reference X
2575 /// type - 0- y 1-z,2 -snp, 3-theta, 4=1/pt
2576 /// marian.ivanov@cern.ch
2577 ///
2578 /// Histo axeses
2579 /// Collection name='TObjArray', class='TObjArray', size=16
2580 /// 0. OBJ: TAxis #Delta #Delta
2581 /// 1. OBJ: TAxis N_{cl} N_{cl}
2582 /// 2. OBJ: TAxis dca_{r} (cm) dca_{r} (cm)
2583 /// 3. OBJ: TAxis z (cm) z (cm)
2584 /// 4. OBJ: TAxis sin(#phi) sin(#phi)
2585 /// 5. OBJ: TAxis tan(#theta) tan(#theta)
2586 /// 6. OBJ: TAxis 1/pt (1/GeV) 1/pt (1/GeV)
2587 /// 7. OBJ: TAxis pt (GeV) pt (GeV)
2588 /// 8. OBJ: TAxis alpha alpha
2589
cfe2c39a 2590 const Int_t kMinEntries=10;
2591 //
2592 // 1. make default selections
2593 //
2594 TH1 * hisDelta=0;
2595 Int_t idim0[4]={0 , 5, 8, 3}; // delta, theta, alpha, z
2596 hisInput->GetAxis(1)->SetRangeUser(110,190); //long tracks
2597 hisInput->GetAxis(2)->SetRangeUser(-10,35); //tracks close to beam pipe
2598 hisInput->GetAxis(4)->SetRangeUser(-0.3,0.3); //small snp at TPC entrance
2599 hisInput->GetAxis(7)->SetRangeUser(3,100); //"high pt tracks"
2600 hisDelta= hisInput->Projection(0);
2601 hisInput->GetAxis(0)->SetRangeUser(-6.*hisDelta->GetRMS(), +6.*hisDelta->GetRMS());
2602 delete hisDelta;
2603 THnSparse *his0= hisInput->Projection(4,idim0);
2604 //
2605 // 2. Get mean in diferent bins
2606 //
8b63d99c 2607 Int_t nbins1=his0->GetAxis(1)->GetNbins();
2608 Int_t first1=his0->GetAxis(1)->GetFirst();
2609 Int_t last1 =his0->GetAxis(1)->GetLast();
2610 //
2611 Double_t bz=AliTrackerBase::GetBz();
cfe2c39a 2612 Int_t idim[4]={0,1, 2, 3}; // delta, theta,alpha,z
2613 //
2614 for (Int_t ibin1=first1; ibin1<=last1; ibin1++){ //axis 1 - theta
2615 //
7d855b04 2616 Double_t x1= his0->GetAxis(1)->GetBinCenter(ibin1);
cfe2c39a 2617 his0->GetAxis(1)->SetRange(TMath::Max(ibin1-1,1),TMath::Min(ibin1+1,nbins1));
8b63d99c 2618 //
8b63d99c 2619 THnSparse * his1 = his0->Projection(4,idim); // projected histogram according range1
2620 Int_t nbins3 = his1->GetAxis(3)->GetNbins();
2621 Int_t first3 = his1->GetAxis(3)->GetFirst();
2622 Int_t last3 = his1->GetAxis(3)->GetLast();
2623 //
cfe2c39a 2624 for (Int_t ibin3=first3-1; ibin3<=last3; ibin3+=1){ // axis 3 - z at "vertex"
8b63d99c 2625 his1->GetAxis(3)->SetRange(TMath::Max(ibin3-1,1),TMath::Min(ibin3+1,nbins3));
2626 Double_t x3= his1->GetAxis(3)->GetBinCenter(ibin3);
2627 if (ibin3<first3) {
2628 his1->GetAxis(3)->SetRangeUser(-1,1);
2629 x3=0;
2630 }
2631 THnSparse * his3= his1->Projection(4,idim); //projected histogram according selection 3
2632 Int_t nbins2 = his3->GetAxis(2)->GetNbins();
2633 Int_t first2 = his3->GetAxis(2)->GetFirst();
2634 Int_t last2 = his3->GetAxis(2)->GetLast();
2635 //
cfe2c39a 2636 for (Int_t ibin2=first2; ibin2<=last2; ibin2+=1){
8b63d99c 2637 his3->GetAxis(2)->SetRange(TMath::Max(ibin2-1,1),TMath::Min(ibin2+1,nbins2));
2638 Double_t x2= his3->GetAxis(2)->GetBinCenter(ibin2);
cfe2c39a 2639 hisDelta = his3->Projection(0);
8b63d99c 2640 //
2641 Double_t entries = hisDelta->GetEntries();
2642 Double_t mean=0, rms=0;
2643 if (entries>kMinEntries){
7d855b04 2644 mean = hisDelta->GetMean();
2645 rms = hisDelta->GetRMS();
8b63d99c 2646 }
cfe2c39a 2647 Double_t sector = 9.*x2/TMath::Pi();
2648 if (sector<0) sector+=18;
2649 Double_t dsec = sector-Int_t(sector)-0.5;
2650 Double_t snp=0; // dummy snp - equal 0
8b63d99c 2651 (*pcstream)<<hname<<
2652 "run="<<run<<
cfe2c39a 2653 "bz="<<bz<< // magnetic field
2654 "theta="<<x1<< // theta
2655 "phi="<<x2<< // phi (alpha)
2656 "z="<<x3<< // z at "vertex"
2657 "snp="<<snp<< // dummy snp
2658 "entries="<<entries<< // entries in bin
2659 "mean="<<mean<< // mean
8b63d99c 2660 "rms="<<rms<<
cfe2c39a 2661 "refX="<<refX<< // track matching refernce plane
2662 "type="<<type<< // parameter type
2663 "sector="<<sector<< // sector
2664 "dsec="<<dsec<< // dummy delta sector
8b63d99c 2665 "\n";
2666 delete hisDelta;
2667 printf("%f\t%f\t%f\t%f\t%f\n",x1,x3,x2, entries,mean);
2668 }
2669 delete his3;
2670 }
2671 delete his1;
2672 }
cfe2c39a 2673 delete his0;
2674}
2675
2676
2677
2678void AliTPCCorrection::MakeDistortionMapSector(THnSparse * hisInput, TTreeSRedirector * const pcstream, const char* hname, Int_t run, Int_t type){
7d855b04 2679 /// make a distortion map out of the residual histogram
2680 /// Results are written to the debug streamer - pcstream
2681 /// Parameters:
2682 /// his0 - input (4D) residual histogram
2683 /// pcstream - file to write the tree
2684 /// run - run number
2685 /// type - 0- y 1-z,2 -snp, 3-theta
2686 /// marian.ivanov@cern.ch
cfe2c39a 2687
2688 //Collection name='TObjArray', class='TObjArray', size=16
2689 //0 OBJ: TAxis delta delta
2690 //1 OBJ: TAxis phi phi
2691 //2 OBJ: TAxis localX localX
2692 //3 OBJ: TAxis kY kY
2693 //4 OBJ: TAxis kZ kZ
2694 //5 OBJ: TAxis is1 is1
2695 //6 OBJ: TAxis is0 is0
2696 //7. OBJ: TAxis z z
2697 //8. OBJ: TAxis IsPrimary IsPrimary
2698
2699 const Int_t kMinEntries=10;
2700 THnSparse * hisSector0=0;
2701 TH1 * htemp=0; // histogram to calculate mean value of parameter
2702 Double_t bz=AliTrackerBase::GetBz();
2703
2704 //
2705 // Loop over pair of sector:
2706 // isPrim - 8 ==> 8
2707 // isec0 - 6 ==> 7
2708 // isec1 - 5 ==> 6
2709 // refX - 2 ==> 5
2710 //
2711 // phi - 1 ==> 4
2712 // z - 7 ==> 3
2713 // snp - 3 ==> 2
2714 // theta- 4 ==> 1
7d855b04 2715 // 0 ==> 0;
cfe2c39a 2716 for (Int_t isec0=0; isec0<72; isec0++){
2717 Int_t index0[9]={0, 4, 3, 7, 1, 2, 5, 6,8}; //regroup indeces
2718 //
2719 //hisInput->GetAxis(8)->SetRangeUser(-0.1,0.4); // select secondaries only ? - get out later ?
2720 hisInput->GetAxis(6)->SetRangeUser(isec0-0.1,isec0+0.1);
2721 hisSector0=hisInput->Projection(7,index0);
2722 //
2723 //
7d855b04 2724 for (Int_t isec1=isec0+1; isec1<72; isec1++){
cfe2c39a 2725 //if (isec1!=isec0+36) continue;
2726 if ( TMath::Abs((isec0%18)-(isec1%18))>1.5 && TMath::Abs((isec0%18)-(isec1%18))<16.5) continue;
2727 printf("Sectors %d\t%d\n",isec1,isec0);
7d855b04 2728 hisSector0->GetAxis(6)->SetRangeUser(isec1-0.1,isec1+0.1);
cfe2c39a 2729 TH1 * hisX=hisSector0->Projection(5);
2730 Double_t refX= hisX->GetMean();
2731 delete hisX;
2732 TH1 *hisDelta=hisSector0->Projection(0);
2733 Double_t dmean = hisDelta->GetMean();
2734 Double_t drms = hisDelta->GetRMS();
2735 hisSector0->GetAxis(0)->SetRangeUser(dmean-5.*drms, dmean+5.*drms);
2736 delete hisDelta;
2737 //
2738 // 1. make default selections
2739 //
2740 Int_t idim0[5]={0 , 1, 2, 3, 4}; // {delta, theta, snp, z, phi }
2741 THnSparse *hisSector1= hisSector0->Projection(5,idim0);
2742 //
2743 // 2. Get mean in diferent bins
2744 //
2745 Int_t idim[5]={0, 1, 2, 3, 4}; // {delta, theta-1,snp-2 ,z-3, phi-4}
2746 //
2747 // Int_t nbinsPhi=hisSector1->GetAxis(4)->GetNbins();
2748 Int_t firstPhi=hisSector1->GetAxis(4)->GetFirst();
2749 Int_t lastPhi =hisSector1->GetAxis(4)->GetLast();
2750 //
2751 for (Int_t ibinPhi=firstPhi; ibinPhi<=lastPhi; ibinPhi+=1){ //axis 4 - phi
2752 //
2753 // Phi loop
2754 //
7d855b04 2755 Double_t xPhi= hisSector1->GetAxis(4)->GetBinCenter(ibinPhi);
cfe2c39a 2756 Double_t psec = (9*xPhi/TMath::Pi());
2757 if (psec<0) psec+=18;
2758 Bool_t isOK0=kFALSE;
2759 Bool_t isOK1=kFALSE;
2760 if (TMath::Abs(psec-isec0%18-0.5)<1. || TMath::Abs(psec-isec0%18-17.5)<1.) isOK0=kTRUE;
2761 if (TMath::Abs(psec-isec1%18-0.5)<1. || TMath::Abs(psec-isec1%18-17.5)<1.) isOK1=kTRUE;
2762 if (!isOK0) continue;
2763 if (!isOK1) continue;
2764 //
2765 hisSector1->GetAxis(4)->SetRange(TMath::Max(ibinPhi-2,firstPhi),TMath::Min(ibinPhi+2,lastPhi));
2766 if (isec1!=isec0+36) {
2767 hisSector1->GetAxis(4)->SetRange(TMath::Max(ibinPhi-3,firstPhi),TMath::Min(ibinPhi+3,lastPhi));
2768 }
2769 //
2770 htemp = hisSector1->Projection(4);
2771 xPhi=htemp->GetMean();
2772 delete htemp;
2773 THnSparse * hisPhi = hisSector1->Projection(4,idim);
2774 //Int_t nbinsZ = hisPhi->GetAxis(3)->GetNbins();
2775 Int_t firstZ = hisPhi->GetAxis(3)->GetFirst();
2776 Int_t lastZ = hisPhi->GetAxis(3)->GetLast();
2777 //
2778 for (Int_t ibinZ=firstZ; ibinZ<=lastZ; ibinZ+=1){ // axis 3 - z
2779 //
2780 // Z loop
2781 //
2782 hisPhi->GetAxis(3)->SetRange(TMath::Max(ibinZ,firstZ),TMath::Min(ibinZ,lastZ));
2783 if (isec1!=isec0+36) {
7d855b04 2784 hisPhi->GetAxis(3)->SetRange(TMath::Max(ibinZ-1,firstZ),TMath::Min(ibinZ-1,lastZ));
cfe2c39a 2785 }
2786 htemp = hisPhi->Projection(3);
2787 Double_t xZ= htemp->GetMean();
2788 delete htemp;
7d855b04 2789 THnSparse * hisZ= hisPhi->Projection(3,idim);
cfe2c39a 2790 //projected histogram according selection 3 -z
2791 //
2792 //
2793 //Int_t nbinsSnp = hisZ->GetAxis(2)->GetNbins();
2794 Int_t firstSnp = hisZ->GetAxis(2)->GetFirst();
2795 Int_t lastSnp = hisZ->GetAxis(2)->GetLast();
2796 for (Int_t ibinSnp=firstSnp; ibinSnp<=lastSnp; ibinSnp+=2){ // axis 2 - snp
2797 //
2798 // Snp loop
2799 //
2800 hisZ->GetAxis(2)->SetRange(TMath::Max(ibinSnp-1,firstSnp),TMath::Min(ibinSnp+1,lastSnp));
2801 if (isec1!=isec0+36) {
2802 hisZ->GetAxis(2)->SetRange(TMath::Max(ibinSnp-2,firstSnp),TMath::Min(ibinSnp+2,lastSnp));
2803 }
2804 htemp = hisZ->Projection(2);
2805 Double_t xSnp= htemp->GetMean();
2806 delete htemp;
7d855b04 2807 THnSparse * hisSnp= hisZ->Projection(2,idim);
cfe2c39a 2808 //projected histogram according selection 2 - snp
7d855b04 2809
cfe2c39a 2810 //Int_t nbinsTheta = hisSnp->GetAxis(1)->GetNbins();
2811 Int_t firstTheta = hisSnp->GetAxis(1)->GetFirst();
2812 Int_t lastTheta = hisSnp->GetAxis(1)->GetLast();
2813 //
2814 for (Int_t ibinTheta=firstTheta; ibinTheta<=lastTheta; ibinTheta+=2){ // axis1 theta
7d855b04 2815
2816
cfe2c39a 2817 hisSnp->GetAxis(1)->SetRange(TMath::Max(ibinTheta-2,firstTheta),TMath::Min(ibinTheta+2,lastTheta));
2818 if (isec1!=isec0+36) {
7d855b04 2819 hisSnp->GetAxis(1)->SetRange(TMath::Max(ibinTheta-3,firstTheta),TMath::Min(ibinTheta+3,lastTheta));
cfe2c39a 2820 }
7d855b04 2821 htemp = hisSnp->Projection(1);
cfe2c39a 2822 Double_t xTheta=htemp->GetMean();
2823 delete htemp;
2824 hisDelta = hisSnp->Projection(0);
2825 //
2826 Double_t entries = hisDelta->GetEntries();
2827 Double_t mean=0, rms=0;
2828 if (entries>kMinEntries){
7d855b04 2829 mean = hisDelta->GetMean();
2830 rms = hisDelta->GetRMS();
cfe2c39a 2831 }
2832 Double_t sector = 9.*xPhi/TMath::Pi();
2833 if (sector<0) sector+=18;
2834 Double_t dsec = sector-Int_t(sector)-0.5;
2835 Int_t dtype=1; // TPC alignment type
2836 (*pcstream)<<hname<<
2837 "run="<<run<<
2838 "bz="<<bz<< // magnetic field
2839 "ptype="<<type<< // parameter type
2840 "dtype="<<dtype<< // parameter type
7d855b04 2841 "isec0="<<isec0<< // sector 0
2842 "isec1="<<isec1<< // sector 1
cfe2c39a 2843 "sector="<<sector<< // sector as float
2844 "dsec="<<dsec<< // delta sector
2845 //
2846 "theta="<<xTheta<< // theta
7d855b04 2847 "phi="<<xPhi<< // phi (alpha)
cfe2c39a 2848 "z="<<xZ<< // z
2849 "snp="<<xSnp<< // snp
2850 //
2851 "entries="<<entries<< // entries in bin
2852 "mean="<<mean<< // mean
7d855b04 2853 "rms="<<rms<< // rms
cfe2c39a 2854 "refX="<<refX<< // track matching reference plane
2855 "\n";
2856 delete hisDelta;
2857 printf("%d\t%d\t%f\t%f\t%f\t%f\t%f\t%f\n",isec0, isec1, xPhi,xZ,xSnp, xTheta, entries,mean);
2858 //
2859 }//ibinTheta
2860 delete hisSnp;
2861 } //ibinSnp
2862 delete hisZ;
2863 }//ibinZ
2864 delete hisPhi;
2865 }//ibinPhi
7d855b04 2866 delete hisSector1;
cfe2c39a 2867 }//isec1
2868 delete hisSector0;
2869 }//isec0
8b63d99c 2870}
2871
2872
2873
2874
2875
cfe2c39a 2876
2877
ffab0c37 2878void AliTPCCorrection::StoreInOCDB(Int_t startRun, Int_t endRun, const char *comment){
7d855b04 2879 /// Store object in the OCDB
2880 /// By default the object is stored in the current directory
2881 /// default comment consit of user name and the date
2882
ffab0c37 2883 TString ocdbStorage="";
2884 ocdbStorage+="local://"+gSystem->GetFromPipe("pwd")+"/OCDB";
2885 AliCDBMetaData *metaData= new AliCDBMetaData();
2886 metaData->SetObjectClassName("AliTPCCorrection");
2887 metaData->SetResponsible("Marian Ivanov");
2888 metaData->SetBeamPeriod(1);
2889 metaData->SetAliRootVersion("05-25-01"); //root version
2890 TString userName=gSystem->GetFromPipe("echo $USER");
2891 TString date=gSystem->GetFromPipe("date");
2892
2893 if (!comment) metaData->SetComment(Form("Space point distortion calibration\n User: %s\n Data%s",userName.Data(),date.Data()));
2894 if (comment) metaData->SetComment(comment);
2895 AliCDBId* id1=NULL;
2896 id1=new AliCDBId("TPC/Calib/Correction", startRun, endRun);
2897 AliCDBStorage* gStorage = AliCDBManager::Instance()->GetStorage(ocdbStorage);
2898 gStorage->Put(this, (*id1), metaData);
2899}
2900
ca58ed4e 2901
7d85e147 2902void AliTPCCorrection::FastSimDistortedVertex(Double_t orgVertex[3], Int_t nTracks, AliESDVertex &aV, AliESDVertex &avOrg, AliESDVertex &cV, AliESDVertex &cvOrg, TTreeSRedirector * const pcstream, Double_t etaCuts){
7d855b04 2903 /// Fast method to simulate the influence of the given distortion on the vertex reconstruction
ca58ed4e 2904
c9cbd2f2 2905 AliMagF* magF= (AliMagF*)TGeoGlobalMagField::Instance()->GetField();
2906 if (!magF) AliError("Magneticd field - not initialized");
2907 Double_t bz = magF->SolenoidField(); //field in kGauss
9f3b99e2 2908 printf("bz: %f\n",bz);
c9cbd2f2 2909 AliVertexerTracks *vertexer = new AliVertexerTracks(bz); // bz in kGauss
ca58ed4e 2910
c9cbd2f2 2911 TObjArray aTrk; // Original Track array of Aside
2912 TObjArray daTrk; // Distorted Track array of A side
2913 UShort_t *aId = new UShort_t[nTracks]; // A side Track ID
7d855b04 2914 TObjArray cTrk;
c9cbd2f2 2915 TObjArray dcTrk;
2916 UShort_t *cId = new UShort_t [nTracks];
7d855b04 2917 Int_t id=0;
ca58ed4e 2918 Double_t mass = TDatabasePDG::Instance()->GetParticle("pi+")->Mass();
7d85e147 2919 TF1 fpt("fpt",Form("x*(1+(sqrt(x*x+%f^2)-%f)/([0]*[1]))^(-[0])",mass,mass),0.4,10);
ca58ed4e 2920 fpt.SetParameters(7.24,0.120);
2921 fpt.SetNpx(10000);
2922 for(Int_t nt=0; nt<nTracks; nt++){
2923 Double_t phi = gRandom->Uniform(0.0, 2*TMath::Pi());
7d85e147 2924 Double_t eta = gRandom->Uniform(-etaCuts, etaCuts);
c9cbd2f2 2925 Double_t pt = fpt.GetRandom(); // momentum for f1
2926 // printf("phi %lf eta %lf pt %lf\n",phi,eta,pt);
ca58ed4e 2927 Short_t sign=1;
2928 if(gRandom->Rndm() < 0.5){
2929 sign =1;
2930 }else{
2931 sign=-1;
2932 }
2933
2934 Double_t theta = 2*TMath::ATan(TMath::Exp(-eta))-TMath::Pi()/2.;
2935 Double_t pxyz[3];
2936 pxyz[0]=pt*TMath::Cos(phi);
2937 pxyz[1]=pt*TMath::Sin(phi);
2938 pxyz[2]=pt*TMath::Tan(theta);
2939 Double_t cv[21]={0};
2940 AliExternalTrackParam *t= new AliExternalTrackParam(orgVertex, pxyz, cv, sign);
2941
2942 Double_t refX=1.;
2943 Int_t dir=-1;
2944 AliExternalTrackParam *td = FitDistortedTrack(*t, refX, dir, NULL);
2945 if (!td) continue;
2946 if (pcstream) (*pcstream)<<"track"<<
2947 "eta="<<eta<<
2948 "theta="<<theta<<
2949 "tOrig.="<<t<<
2950 "td.="<<td<<
2951 "\n";
7d85e147 2952 if(( eta>0.07 )&&( eta<etaCuts )) { // - log(tan(0.5*theta)), theta = 0.5*pi - ATan(5.0/80.0)
ca58ed4e 2953 if (td){
c9cbd2f2 2954 daTrk.AddLast(td);
2955 aTrk.AddLast(t);
2956 Int_t nn=aTrk.GetEntriesFast();
2957 aId[nn]=id;
ca58ed4e 2958 }
7d85e147 2959 }else if(( eta<-0.07 )&&( eta>-etaCuts )){
ca58ed4e 2960 if (td){
c9cbd2f2 2961 dcTrk.AddLast(td);
2962 cTrk.AddLast(t);
2963 Int_t nn=cTrk.GetEntriesFast();
2964 cId[nn]=id;
ca58ed4e 2965 }
2966 }
7d855b04 2967 id++;
ca58ed4e 2968 }// end of track loop
2969
2970 vertexer->SetTPCMode();
2971 vertexer->SetConstraintOff();
2972
7d855b04 2973 aV = *((AliESDVertex*)vertexer->FindPrimaryVertex(&daTrk,aId));
c9cbd2f2 2974 avOrg = *((AliESDVertex*)vertexer->FindPrimaryVertex(&aTrk,aId));
7d855b04 2975 cV = *((AliESDVertex*)vertexer->FindPrimaryVertex(&dcTrk,cId));
c9cbd2f2 2976 cvOrg = *((AliESDVertex*)vertexer->FindPrimaryVertex(&cTrk,cId));
ca58ed4e 2977 if (pcstream) (*pcstream)<<"vertex"<<
2978 "x="<<orgVertex[0]<<
2979 "y="<<orgVertex[1]<<
2980 "z="<<orgVertex[2]<<
2981 "av.="<<&aV<< // distorted vertex A side
2982 "cv.="<<&cV<< // distroted vertex C side
2983 "avO.="<<&avOrg<< // original vertex A side
2984 "cvO.="<<&cvOrg<<
2985 "\n";
c9cbd2f2 2986 delete []aId;
2987 delete []cId;
ca58ed4e 2988}
f1817479 2989
2990void AliTPCCorrection::AddVisualCorrection(AliTPCCorrection* corr, Int_t position){
7d855b04 2991 /// make correction available for visualization using
2992 /// TFormula, TFX and TTree::Draw
2993 /// important in order to check corrections and also compute dervied variables
2994 /// e.g correction partial derivatives
2995 ///
2996 /// NOTE - class is not owner of correction
2997
cfe2c39a 2998 if (!fgVisualCorrection) fgVisualCorrection=new TObjArray(10000);
2999 if (position>=fgVisualCorrection->GetEntriesFast())
3000 fgVisualCorrection->Expand((position+10)*2);
f1817479 3001 fgVisualCorrection->AddAt(corr, position);
3002}
3003
7d855b04 3004AliTPCCorrection* AliTPCCorrection::GetVisualCorrection(Int_t position) {
3005 /// Get visula correction registered at index=position
3006
ad5a2460 3007 return fgVisualCorrection? (AliTPCCorrection*)fgVisualCorrection->At(position):0;
3008}
3009
f1817479 3010
3011
287fbdfa 3012Double_t AliTPCCorrection::GetCorrSector(Double_t sector, Double_t r, Double_t kZ, Int_t axisType, Int_t corrType){
7d855b04 3013 /// calculate the correction at given position - check the geffCorr
3014 ///
3015 /// corrType return values
3016 /// 0 - delta R
3017 /// 1 - delta RPhi
3018 /// 2 - delta Z
3019 /// 3 - delta RPHI
3020
f1817479 3021 if (!fgVisualCorrection) return 0;
3022 AliTPCCorrection *corr = (AliTPCCorrection*)fgVisualCorrection->At(corrType);
3023 if (!corr) return 0;
25732bff 3024
f1817479 3025 Double_t phi=sector*TMath::Pi()/9.;
287fbdfa 3026 Double_t gx = r*TMath::Cos(phi);
3027 Double_t gy = r*TMath::Sin(phi);
3028 Double_t gz = r*kZ;
7d855b04 3029 Int_t nsector=(gz>=0) ? 0:18;
f1817479 3030 //
3031 //
3032 //
2942f542 3033 Float_t distPoint[3]={static_cast<Float_t>(gx),static_cast<Float_t>(gy),static_cast<Float_t>(gz)};
f1817479 3034 corr->DistortPoint(distPoint, nsector);
3035 Double_t r0=TMath::Sqrt(gx*gx+gy*gy);
3036 Double_t r1=TMath::Sqrt(distPoint[0]*distPoint[0]+distPoint[1]*distPoint[1]);
3037 Double_t phi0=TMath::ATan2(gy,gx);
3038 Double_t phi1=TMath::ATan2(distPoint[1],distPoint[0]);
3039 if (axisType==0) return r1-r0;
3040 if (axisType==1) return (phi1-phi0)*r0;
3041 if (axisType==2) return distPoint[2]-gz;
cfe2c39a 3042 if (axisType==3) return (TMath::Cos(phi)*(distPoint[0]-gx)+ TMath::Cos(phi)*(distPoint[1]-gy));
f1817479 3043 return phi1-phi0;
3044}
3045
3046Double_t AliTPCCorrection::GetCorrXYZ(Double_t gx, Double_t gy, Double_t gz, Int_t axisType, Int_t corrType){
7d855b04 3047 /// return correction at given x,y,z
3048
f1817479 3049 if (!fgVisualCorrection) return 0;
3050 AliTPCCorrection *corr = (AliTPCCorrection*)fgVisualCorrection->At(corrType);
3051 if (!corr) return 0;
3052 Double_t phi0= TMath::ATan2(gy,gx);
7d855b04 3053 Int_t nsector=(gz>=0) ? 0:18;
2942f542 3054 Float_t distPoint[3]={static_cast<Float_t>(gx),static_cast<Float_t>(gy),static_cast<Float_t>(gz)};
2d4e971f 3055 corr->CorrectPoint(distPoint, nsector);
f1817479 3056 Double_t r0=TMath::Sqrt(gx*gx+gy*gy);
3057 Double_t r1=TMath::Sqrt(distPoint[0]*distPoint[0]+distPoint[1]*distPoint[1]);
3058 Double_t phi1=TMath::ATan2(distPoint[1],distPoint[0]);
3059 if (axisType==0) return r1-r0;
3060 if (axisType==1) return (phi1-phi0)*r0;
3061 if (axisType==2) return distPoint[2]-gz;
3062 return phi1-phi0;
3063}
46e89793 3064
fdbbc146 3065Double_t AliTPCCorrection::GetCorrXYZDz(Double_t gx, Double_t gy, Double_t gz, Int_t axisType, Int_t corrType,Double_t delta){
7d855b04 3066 /// return correction at given x,y,z
3067
fdbbc146 3068 if (!fgVisualCorrection) return 0;
3069 AliTPCCorrection *corr = (AliTPCCorrection*)fgVisualCorrection->At(corrType);
3070 if (!corr) return 0;
3071 Double_t phi0= TMath::ATan2(gy,gx);
7d855b04 3072 Int_t nsector=(gz>=0) ? 0:18;
2942f542 3073 Float_t distPoint[3]={static_cast<Float_t>(gx),static_cast<Float_t>(gy),static_cast<Float_t>(gz)};
3074 Float_t dxyz[3]={static_cast<Float_t>(gx),static_cast<Float_t>(gy),static_cast<Float_t>(gz)};
fdbbc146 3075 //
3076 corr->GetCorrectionDz(distPoint, nsector,dxyz,delta);
2d4e971f 3077 distPoint[0]+=dxyz[0];
3078 distPoint[1]+=dxyz[1];
3079 distPoint[2]+=dxyz[2];
fdbbc146 3080 Double_t r0=TMath::Sqrt(gx*gx+gy*gy);
3081 Double_t r1=TMath::Sqrt(distPoint[0]*distPoint[0]+distPoint[1]*distPoint[1]);
3082 Double_t phi1=TMath::ATan2(distPoint[1],distPoint[0]);
3083 if (axisType==0) return r1-r0;
3084 if (axisType==1) return (phi1-phi0)*r0;
3085 if (axisType==2) return distPoint[2]-gz;
3086 return phi1-phi0;
3087}
3088
3089Double_t AliTPCCorrection::GetCorrXYZIntegrateZ(Double_t gx, Double_t gy, Double_t gz, Int_t axisType, Int_t corrType,Double_t delta){
7d855b04 3090 /// return correction at given x,y,z
3091
fdbbc146 3092 if (!fgVisualCorrection) return 0;
3093 AliTPCCorrection *corr = (AliTPCCorrection*)fgVisualCorrection->At(corrType);
3094 if (!corr) return 0;
3095 Double_t phi0= TMath::ATan2(gy,gx);
7d855b04 3096 Int_t nsector=(gz>=0) ? 0:18;
2942f542 3097 Float_t distPoint[3]={static_cast<Float_t>(gx),static_cast<Float_t>(gy),static_cast<Float_t>(gz)};
3098 Float_t dxyz[3]={static_cast<Float_t>(gx),static_cast<Float_t>(gy),static_cast<Float_t>(gz)};
fdbbc146 3099 //
3100 corr->GetCorrectionIntegralDz(distPoint, nsector,dxyz,delta);
2d4e971f 3101 distPoint[0]+=dxyz[0];
3102 distPoint[1]+=dxyz[1];
3103 distPoint[2]+=dxyz[2];
3104 Double_t r0=TMath::Sqrt(gx*gx+gy*gy);
3105 Double_t r1=TMath::Sqrt(distPoint[0]*distPoint[0]+distPoint[1]*distPoint[1]);
3106 Double_t phi1=TMath::ATan2(distPoint[1],distPoint[0]);
3107 if (axisType==0) return r1-r0;
3108 if (axisType==1) return (phi1-phi0)*r0;
3109 if (axisType==2) return distPoint[2]-gz;
3110 return phi1-phi0;
3111}
3112
3113
3114Double_t AliTPCCorrection::GetDistXYZ(Double_t gx, Double_t gy, Double_t gz, Int_t axisType, Int_t corrType){
7d855b04 3115 /// return correction at given x,y,z
3116
2d4e971f 3117 if (!fgVisualCorrection) return 0;
3118 AliTPCCorrection *corr = (AliTPCCorrection*)fgVisualCorrection->At(corrType);
3119 if (!corr) return 0;
3120 Double_t phi0= TMath::ATan2(gy,gx);
3121 Int_t nsector=(gz>=0) ? 0:18;
2942f542 3122 Float_t distPoint[3]={static_cast<Float_t>(gx),static_cast<Float_t>(gy),static_cast<Float_t>(gz)};
2d4e971f 3123 corr->DistortPoint(distPoint, nsector);
fdbbc146 3124 Double_t r0=TMath::Sqrt(gx*gx+gy*gy);
3125 Double_t r1=TMath::Sqrt(distPoint[0]*distPoint[0]+distPoint[1]*distPoint[1]);
3126 Double_t phi1=TMath::ATan2(distPoint[1],distPoint[0]);
3127 if (axisType==0) return r1-r0;
3128 if (axisType==1) return (phi1-phi0)*r0;
3129 if (axisType==2) return distPoint[2]-gz;
3130 return phi1-phi0;
3131}
3132
2d4e971f 3133Double_t AliTPCCorrection::GetDistXYZDz(Double_t gx, Double_t gy, Double_t gz, Int_t axisType, Int_t corrType,Double_t delta){
7d855b04 3134 /// return correction at given x,y,z
3135
2d4e971f 3136 if (!fgVisualCorrection) return 0;
3137 AliTPCCorrection *corr = (AliTPCCorrection*)fgVisualCorrection->At(corrType);
3138 if (!corr) return 0;
3139 Double_t phi0= TMath::ATan2(gy,gx);
3140 Int_t nsector=(gz>=0) ? 0:18;
2942f542 3141 Float_t distPoint[3]={static_cast<Float_t>(gx),static_cast<Float_t>(gy),static_cast<Float_t>(gz)};
3142 Float_t dxyz[3]={static_cast<Float_t>(gx),static_cast<Float_t>(gy),static_cast<Float_t>(gz)};
2d4e971f 3143 //
3144 corr->GetDistortionDz(distPoint, nsector,dxyz,delta);
3145 distPoint[0]+=dxyz[0];
3146 distPoint[1]+=dxyz[1];
3147 distPoint[2]+=dxyz[2];
3148 Double_t r0=TMath::Sqrt(gx*gx+gy*gy);
3149 Double_t r1=TMath::Sqrt(distPoint[0]*distPoint[0]+distPoint[1]*distPoint[1]);
3150 Double_t phi1=TMath::ATan2(distPoint[1],distPoint[0]);
3151 if (axisType==0) return r1-r0;
3152 if (axisType==1) return (phi1-phi0)*r0;
3153 if (axisType==2) return distPoint[2]-gz;
3154 return phi1-phi0;
3155}
46e89793 3156
2d4e971f 3157Double_t AliTPCCorrection::GetDistXYZIntegrateZ(Double_t gx, Double_t gy, Double_t gz, Int_t axisType, Int_t corrType,Double_t delta){
7d855b04 3158 /// return correction at given x,y,z
3159
2d4e971f 3160 if (!fgVisualCorrection) return 0;
3161 AliTPCCorrection *corr = (AliTPCCorrection*)fgVisualCorrection->At(corrType);
3162 if (!corr) return 0;
3163 Double_t phi0= TMath::ATan2(gy,gx);
3164 Int_t nsector=(gz>=0) ? 0:18;
2942f542 3165 Float_t distPoint[3]={static_cast<Float_t>(gx),static_cast<Float_t>(gy),static_cast<Float_t>(gz)};
3166 Float_t dxyz[3]={static_cast<Float_t>(gx),static_cast<Float_t>(gy),static_cast<Float_t>(gz)};
2d4e971f 3167 //
3168 corr->GetDistortionIntegralDz(distPoint, nsector,dxyz,delta);
3169 distPoint[0]+=dxyz[0];
3170 distPoint[1]+=dxyz[1];
3171 distPoint[2]+=dxyz[2];
3172 Double_t r0=TMath::Sqrt(gx*gx+gy*gy);
3173 Double_t r1=TMath::Sqrt(distPoint[0]*distPoint[0]+distPoint[1]*distPoint[1]);
3174 Double_t phi1=TMath::ATan2(distPoint[1],distPoint[0]);
3175 if (axisType==0) return r1-r0;
3176 if (axisType==1) return (phi1-phi0)*r0;
3177 if (axisType==2) return distPoint[2]-gz;
3178 return phi1-phi0;
3179}
46e89793 3180
3181
3182
284418bc 3183void AliTPCCorrection::MakeLaserDistortionTree(TTree* tree, TObjArray */*corrArray*/, Int_t /*itype*/){
7d855b04 3184 /// Make a laser fit tree for global minimization
3185
3186 AliTPCcalibDB* calib=AliTPCcalibDB::Instance();
3187 AliTPCCorrection * correction = calib->GetTPCComposedCorrection();
3188 if (!correction) correction = calib->GetTPCComposedCorrection(AliTrackerBase::GetBz());
46e89793 3189 correction->AddVisualCorrection(correction,0); //register correction
3190
284418bc 3191 // AliTPCTransform *transform = AliTPCcalibDB::Instance()->GetTransform() ;
3192 //AliTPCParam *param = AliTPCcalibDB::Instance()->GetParameters();
46e89793 3193 //
3194 const Double_t cutErrY=0.05;
3195 const Double_t kSigmaCut=4;
3196 // const Double_t cutErrZ=0.03;
3197 const Double_t kEpsilon=0.00000001;
284418bc 3198 // const Double_t kMaxDist=1.; // max distance - space correction
46e89793 3199 TVectorD *vecdY=0;
3200 TVectorD *vecdZ=0;
3201 TVectorD *veceY=0;
3202 TVectorD *veceZ=0;
3203 AliTPCLaserTrack *ltr=0;
3204 AliTPCLaserTrack::LoadTracks();
3205 tree->SetBranchAddress("dY.",&vecdY);
3206 tree->SetBranchAddress("dZ.",&vecdZ);
3207 tree->SetBranchAddress("eY.",&veceY);
3208 tree->SetBranchAddress("eZ.",&veceZ);
3209 tree->SetBranchAddress("LTr.",&ltr);
3210 Int_t entries= tree->GetEntries();
3211 TTreeSRedirector *pcstream= new TTreeSRedirector("distortionLaser_0.root");
3212 Double_t bz=AliTrackerBase::GetBz();
7d855b04 3213 //
284418bc 3214 // Double_t globalXYZ[3];
3215 //Double_t globalXYZCorr[3];
46e89793 3216 for (Int_t ientry=0; ientry<entries; ientry++){
3217 tree->GetEntry(ientry);
3218 if (!ltr->GetVecGX()){
3219 ltr->UpdatePoints();
3220 }
3221 //
3222 TVectorD fit10(5);
3223 TVectorD fit5(5);
3224 printf("Entry\t%d\n",ientry);
3225 for (Int_t irow0=0; irow0<158; irow0+=1){
7d855b04 3226 //
46e89793 3227 TLinearFitter fitter10(4,"hyp3");
3228 TLinearFitter fitter5(2,"hyp1");
3229 Int_t sector= (Int_t)(*ltr->GetVecSec())[irow0];
3230 if (sector<0) continue;
3231 //if (TMath::Abs(vecdY->GetMatrixArray()[irow0])<kEpsilon) continue;
3232
3233 Double_t refX= (*ltr->GetVecLX())[irow0];
3234 Int_t firstRow1 = TMath::Max(irow0-10,0);
3235 Int_t lastRow1 = TMath::Min(irow0+10,158);
3236 Double_t padWidth=(irow0<64)?0.4:0.6;
3237 // make long range fit
3238 for (Int_t irow1=firstRow1; irow1<=lastRow1; irow1++){
3239 if (TMath::Abs((*ltr->GetVecSec())[irow1]-sector)>kEpsilon) continue;
3240 if (veceY->GetMatrixArray()[irow1]>cutErrY) continue;
3241 if (TMath::Abs(vecdY->GetMatrixArray()[irow1])<kEpsilon) continue;
3242 Double_t idealX= (*ltr->GetVecLX())[irow1];
3243 Double_t idealY= (*ltr->GetVecLY())[irow1];
284418bc 3244 // Double_t idealZ= (*ltr->GetVecLZ())[irow1];
46e89793 3245 Double_t gx= (*ltr->GetVecGX())[irow1];
3246 Double_t gy= (*ltr->GetVecGY())[irow1];
3247 Double_t gz= (*ltr->GetVecGZ())[irow1];
3248 Double_t measY=(*vecdY)[irow1]+idealY;
3249 Double_t deltaR = GetCorrXYZ(gx, gy, gz, 0,0);
3250 // deltaR = R distorted -R ideal
3251 Double_t xxx[4]={idealX+deltaR-refX,TMath::Cos(idealY/padWidth), TMath::Sin(idealY/padWidth)};
3252 fitter10.AddPoint(xxx,measY,1);
3253 }
3254 Bool_t isOK=kTRUE;
3255 Double_t rms10=0;//TMath::Sqrt(fitter10.GetChisquare()/(fitter10.GetNpoints()-4));
3256 Double_t mean10 =0;// fitter10.GetParameter(0);
3257 Double_t slope10 =0;// fitter10.GetParameter(0);
3258 Double_t cosPart10 = 0;// fitter10.GetParameter(2);
7d855b04 3259 Double_t sinPart10 =0;// fitter10.GetParameter(3);
46e89793 3260
3261 if (fitter10.GetNpoints()>10){
3262 fitter10.Eval();
3263 rms10=TMath::Sqrt(fitter10.GetChisquare()/(fitter10.GetNpoints()-4));
3264 mean10 = fitter10.GetParameter(0);
3265 slope10 = fitter10.GetParameter(1);
3266 cosPart10 = fitter10.GetParameter(2);
7d855b04 3267 sinPart10 = fitter10.GetParameter(3);
46e89793 3268 //
3269 // make short range fit
3270 //
3271 for (Int_t irow1=firstRow1+5; irow1<=lastRow1-5; irow1++){
3272 if (TMath::Abs((*ltr->GetVecSec())[irow1]-sector)>kEpsilon) continue;
3273 if (veceY->GetMatrixArray()[irow1]>cutErrY) continue;
3274 if (TMath::Abs(vecdY->GetMatrixArray()[irow1])<kEpsilon) continue;
3275 Double_t idealX= (*ltr->GetVecLX())[irow1];
3276 Double_t idealY= (*ltr->GetVecLY())[irow1];
284418bc 3277 // Double_t idealZ= (*ltr->GetVecLZ())[irow1];
46e89793 3278 Double_t gx= (*ltr->GetVecGX())[irow1];
3279 Double_t gy= (*ltr->GetVecGY())[irow1];
3280 Double_t gz= (*ltr->GetVecGZ())[irow1];
3281 Double_t measY=(*vecdY)[irow1]+idealY;
3282 Double_t deltaR = GetCorrXYZ(gx, gy, gz, 0,0);
7d855b04 3283 // deltaR = R distorted -R ideal
46e89793 3284 Double_t expY= mean10+slope10*(idealX+deltaR-refX);
3285 if (TMath::Abs(measY-expY)>kSigmaCut*rms10) continue;
3286 //
3287 Double_t corr=cosPart10*TMath::Cos(idealY/padWidth)+sinPart10*TMath::Sin(idealY/padWidth);
3288 Double_t xxx[4]={idealX+deltaR-refX,TMath::Cos(idealY/padWidth), TMath::Sin(idealY/padWidth)};
3289 fitter5.AddPoint(xxx,measY-corr,1);
7d855b04 3290 }
46e89793 3291 }else{
3292 isOK=kFALSE;
3293 }
3294 if (fitter5.GetNpoints()<8) isOK=kFALSE;
3295
3296 Double_t rms5=0;//TMath::Sqrt(fitter5.GetChisquare()/(fitter5.GetNpoints()-4));
3297 Double_t offset5 =0;// fitter5.GetParameter(0);
7d855b04 3298 Double_t slope5 =0;// fitter5.GetParameter(0);
46e89793 3299 if (isOK){
3300 fitter5.Eval();
3301 rms5=TMath::Sqrt(fitter5.GetChisquare()/(fitter5.GetNpoints()-4));
3302 offset5 = fitter5.GetParameter(0);
7d855b04 3303 slope5 = fitter5.GetParameter(0);
46e89793 3304 }
3305 //
3306 Double_t dtype=5;
3307 Double_t ptype=0;
3308 Double_t phi =(*ltr->GetVecPhi())[irow0];
3309 Double_t theta =ltr->GetTgl();
3310 Double_t mean=(vecdY)->GetMatrixArray()[irow0];
3311 Double_t gx=0,gy=0,gz=0;
3312 Double_t snp = (*ltr->GetVecP2())[irow0];
3313 Int_t bundle= ltr->GetBundle();
3314 Int_t id= ltr->GetId();
3315 // Double_t rms = err->GetMatrixArray()[irow];
3316 //
3317 gx = (*ltr->GetVecGX())[irow0];
3318 gy = (*ltr->GetVecGY())[irow0];
3319 gz = (*ltr->GetVecGZ())[irow0];
3320 Double_t dRrec = GetCorrXYZ(gx, gy, gz, 0,0);
3321 fitter10.GetParameters(fit10);
7d855b04 3322 fitter5.GetParameters(fit5);
46e89793 3323 Double_t idealY= (*ltr->GetVecLY())[irow0];
3324 Double_t measY=(*vecdY)[irow0]+idealY;
3325 Double_t corr=cosPart10*TMath::Cos(idealY/padWidth)+sinPart10*TMath::Sin(idealY/padWidth);
3326 if (TMath::Max(rms5,rms10)>0.06) isOK=kFALSE;
3327 //
3328 (*pcstream)<<"fitFull"<< // dumpe also intermediate results
3329 "bz="<<bz<< // magnetic filed used
3330 "dtype="<<dtype<< // detector match type
3331 "ptype="<<ptype<< // parameter type
3332 "theta="<<theta<< // theta
7d855b04 3333 "phi="<<phi<< // phi
46e89793 3334 "snp="<<snp<< // snp
3335 "sector="<<sector<<
3336 "bundle="<<bundle<<
3337// // "dsec="<<dsec<<
3338 "refX="<<refX<< // reference radius
3339 "gx="<<gx<< // global position
3340 "gy="<<gy<< // global position
3341 "gz="<<gz<< // global position
3342 "dRrec="<<dRrec<< // delta Radius in reconstruction
3343 "id="<<id<< //bundle
3344 "rms10="<<rms10<<
3345 "rms5="<<rms5<<
3346 "fit10.="<<&fit10<<
3347 "fit5.="<<&fit5<<
3348 "measY="<<measY<<
3349 "mean="<<mean<<
3350 "idealY="<<idealY<<
3351 "corr="<<corr<<
3352 "isOK="<<isOK<<
3353 "\n";
3354 }
3355 }
3356 delete pcstream;
3357}