]> git.uio.no Git - u/mrichter/AliRoot.git/blob - TOF/AliTOFGeometry.cxx
Histograms of time vs. TRM enabled for DQM
[u/mrichter/AliRoot.git] / TOF / AliTOFGeometry.cxx
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
16 /*
17 $Log$
18 Revision 1.20.1  2007/05/19 decaro
19          Added the following methods:
20              GetVolumeIndices(Int_t index, Int_t *det), to get
21           the volume indices (sector, plate, strip, padz, padx,
22           stored respectively in det[0], det[1], det[2], det[3], det[4])
23           from the calibration channel index;
24              NStrip(Int_t nPlate), to get the strips number
25           per each kind of TOF module.
26
27 Revision 1.20  2007/10/08 17:52:55  decaro
28 hole region in front of PHOS detector: update of sectors' numbers
29
30 Revision 1.19  2007/10/04 14:05:09  zampolli
31 AliTOFGeometryV5 becoming AliTOFGeometry
32
33 Revision 1.18  2007/02/19 18:55:26  decaro
34 Added getter methods for volume path (for Event Display)
35
36 Revision 1.17.1  2006/12/15 
37          Added method DetToStripRF(...) to get
38          a pad corner coordinates in its strip reference frame
39          (A.De Caro, M.Di Stefano)
40 Revision 1.17  2006/08/22 13:30:02  arcelli
41 removal of effective c++ warnings (C.Zampolli)
42
43 Revision 1.16  2006/04/20 22:30:50  hristov
44 Coding conventions (Annalisa)
45
46 Revision 1.15  2006/04/16 22:29:05  hristov
47 Coding conventions (Annalisa)
48
49 Revision 1.14  2006/04/05 08:35:38  hristov
50 Coding conventions (S.Arcelli, C.Zampolli)
51
52 Revision 1.13  2006/03/12 14:37:54  arcelli
53  Changes for TOF Reconstruction using TGeo
54
55 Revision 1.12  2006/02/28 10:38:00  decaro
56 AliTOFGeometry::fAngles, AliTOFGeometry::fHeights, AliTOFGeometry::fDistances arrays: dimension definition in the right location
57
58 Revision 1.11  2005/12/15 14:17:29  decaro
59 Correction of some parameter values
60
61 Revision 1.10  2005/12/15 08:55:32  decaro
62 New TOF geometry description (V5) -G. Cara Romeo and A. De Caro
63
64 Revision 1.9.1  2005/07/19 A. De Caro
65         Created daughter-classes AliTOFGeometryV4 and AliTOFGeometryV5
66         => moved global methods IsInsideThePad, DistanceToPad,
67         GetPlate, GetSector, GetStrip, GetPadX, GetPadZ,
68         GetX, GetY, GetZ, GetPadDx, GetPadDy and GetPadDz
69         in daughter-classes
70
71 Revision 1.9  2005/10/20 12:41:35  hristov
72 Implementation of parallel tracking. It is not the default version, one can use it passing option MI from AliReconstruction to TOF (M.Ivanov)
73
74 Revision 1.8  2004/11/29 08:28:01  decaro
75 Introduction of a new TOF constant (i.e. TDC bin width)
76
77 Revision 1.7  2004/11/05 07:20:08  decaro
78 TOF library splitting and conversion of some printout messages in AliLog schema (T.Kuhr)
79
80 Revision 1.6  2004/06/15 15:27:59  decaro
81 TOF raw data: preliminary implementation and style changes
82
83 Revision 1.5  2004/04/20 14:37:22  hristov
84 Using TMath::Abs instead of fabs, arrays of variable size created/deleted correctly (HP,Sun)
85
86 Revision 1.4  2004/04/13 09:42:51  decaro
87 Track reconstruction code for TOF: updating
88
89 Revision 1.3  2003/12/29 18:40:39  hristov
90 Copy/paste error corrected
91
92 Revision 1.2  2003/12/29 17:26:01  hristov
93 Using enum to initaialize static ints in the header file, the initialization of static floats moved to the implementation file
94
95 Revision 1.1  2003/12/29 15:18:03  decaro
96 TOF geometry updating (addition of AliTOFGeometry)
97
98 Revision 0.05  2004/6/11 A.De Caro
99         Implement Global method NpadXStrip
100         Insert four float constants (originally  in AliTOF class)
101 Revision 0.04  2004/4/05 S.Arcelli
102         Implement Global methods IsInsideThePad 
103                                   DistanceToPad 
104 Revision 0.03  2003/12/14 S.Arcelli
105         Set Phi range [-180,180]->[0,360] 
106 Revision 0.02  2003/12/10 S.Arcelli:
107         Implement Global methods GetPos & GetDetID 
108 Revision 0.01  2003/12/04 S.Arcelli
109 */
110
111 ///////////////////////////////////////////////////////////////////////////////
112 //                                                                           //
113 //  TOF Geometry class                                                       //
114 //                                                                           //
115 ///////////////////////////////////////////////////////////////////////////////
116
117 #include "TGeoManager.h"
118 //#include "TGeoMatrix.h"
119 #include "TMath.h"
120
121 #include "AliConst.h"
122 #include "AliGeomManager.h"
123 #include "AliLog.h"
124
125 #include "AliTOFGeometry.h"
126
127 extern TGeoManager *gGeoManager;
128
129 ClassImp(AliTOFGeometry)
130
131 const Float_t AliTOFGeometry::fgkZlenA    = 370.6*2.; // length (cm) of the A module
132 const Float_t AliTOFGeometry::fgkZlenB    = 146.5;    // length (cm) of the B module
133 const Float_t AliTOFGeometry::fgkZlenC    = 170.45;   // length (cm) of the C module
134 const Float_t AliTOFGeometry::fgkMaxhZtof = 370.6;    // Max half z-size of TOF (cm)
135
136 const Float_t AliTOFGeometry::fgkxTOF     = 372.00;// Inner radius of the TOF for Reconstruction (cm)
137 const Float_t AliTOFGeometry::fgkRmin     = 371.00;// Inner radius of the TOF (cm)
138 const Float_t AliTOFGeometry::fgkRmax     = 400.05;// Outer radius of the TOF (cm)
139
140 const Float_t AliTOFGeometry::fgkXPad     = 2.5;    // Pad size in the x direction (cm)
141 const Float_t AliTOFGeometry::fgkZPad     = 3.5;    // Pad size in the z direction (cm)
142
143 const Float_t AliTOFGeometry::fgkStripLength = 122.;// Strip Length (rho X phi direction) (cm)
144
145 const Float_t AliTOFGeometry::fgkSigmaForTail1= 2.; //Sig1 for simulation of TDC tails 
146 const Float_t AliTOFGeometry::fgkSigmaForTail2= 0.5;//Sig2 for simulation of TDC tails
147
148 const Float_t AliTOFGeometry::fgkPhiSec= 20;//sector Phi width (deg)
149
150 const Float_t AliTOFGeometry::fgkTdcBin = 24.4;     // time-of-flight bin width [ps]
151 const Float_t AliTOFGeometry::fgkToTBin = 48.8;     // time-over-threshold bin width [ps]
152 const Float_t AliTOFGeometry::fgkBunchCrossingBin = fgkTdcBin * 1024; // bunch-crossing bin width [ps]
153
154 const Float_t AliTOFGeometry::fgkSlewTOTMin = 10.; // min TOT for slewing correction [ns]
155 const Float_t AliTOFGeometry::fgkSlewTOTMax = 16.; // max TOT for slewing correction [ns]
156
157 const Float_t AliTOFGeometry::fgkDeadTime = 25E+03;        // Single channel dead time (ps)
158 const Float_t AliTOFGeometry::fgkMatchingWindow = fgkTdcBin*TMath::Power(2,13); // Matching window  (ps)
159
160 const Float_t AliTOFGeometry::fgkAngles[kNPlates][kMaxNstrip] = {
161     { 43.99,  43.20,  42.40,  41.59,  40.77,  39.94,  39.11,  38.25,  37.40,  36.53,
162       35.65,  34.76,  33.87,  32.96,  32.05,  31.13,  30.19,  29.24,  12.33,  0.00},
163
164     { 27.26,  26.28,  25.30,  24.31,  23.31,  22.31,  21.30,  20.29,  19.26,  18.24,
165       17.20,  16.16,  15.11,  14.05,  13.00,  11.93,  10.87,   9.80,   8.74,  0.00},
166
167     {  0.00,   6.30,   5.31,   4.25,   3.19,   2.12,   1.06,   0.00,  -1.06,  -2.12,
168       -3.19,  -4.25,  -5.31,  -6.30,   0.00,   0.00,   0.00,   0.00,   0.00,  0.00},
169
170     { -8.74,  -9.80, -10.87, -11.93, -13.00, -14.05, -15.11, -16.16, -17.20, -18.24,
171      -19.26, -20.29, -21.30, -22.31, -23.31, -24.31, -25.30, -26.28, -27.26,  0.00},
172     
173     {-12.33, -29.24, -30.19, -31.13, -32.05, -32.96, -33.87, -34.76, -35.65, -36.53,
174      -37.40, -38.25, -39.11, -39.94, -40.77, -41.59, -42.40, -43.20, -43.99,  0.00}
175   };
176
177 /*
178 const Float_t AliTOFGeometry::fgkHeights[kNPlates][kMaxNstrip] = {
179     {-8.2,  -7.5,  -8.2,  -7.7,  -8.1,  -7.6,  -7.7,  -7.7,  -7.7,  -7.7,
180      -7.5,  -7.2,  -7.3,  -7.5,  -7.6,  -7.8,  -8.3,  -9.3,  -3.1,   0.0},
181
182     {-7.9,  -8.1,  -8.5,  -9.0, -10.1,  -3.9,  -5.9,  -7.7, -10.1,  -3.6,
183      -5.8,  -8.0, -10.4,  -4.4,  -7.2, -10.2,  -4.6,  -7.4, -10.4,   0.0},
184
185     {-2.5, -10.4,  -5.0,  -9.9,  -4.8,  -9.9,  -4.7, -10.2,  -4.7,  -9.9,
186      -4.8,  -9.9,  -5.0, -10.4,  -2.5,   0.0,   0.0,   0.0,   0.0,   0.0},
187
188     {-10.4, -7.4,  -4.6, -10.2,  -7.2,  -4.4, -10.4,  -8.0,  -5.8,  -3.6,
189      -10.1, -7.7,  -5.9,  -3.9, -10.1,  -9.0,  -8.5,  -8.1,  -7.9,   0.0},
190
191     { -3.1, -9.3,  -8.3,  -7.8,  -7.6,  -7.5,  -7.3,  -7.2,  -7.5,  -7.7,
192       -7.7, -7.7,  -7.7,  -7.6,  -8.1,  -7.7,  -8.2,  -7.5,  -8.2,   0.0}
193   };
194 */
195 /*
196 const Float_t AliTOFGeometry::fgkHeights[kNPlates][kMaxNstrip] = {
197   {  -8.405, -10.885,  -8.405,  -7.765,  -8.285,  -7.745,  -7.865,  -7.905,  -7.895,  -7.885,
198      -7.705,  -7.395,  -7.525,  -7.645, -11.285, -10.355,  -8.365,  -9.385,  -3.255,   0.000 },
199   {  -7.905,  -8.235,  -8.605,  -9.045, -10.205,  -3.975,  -5.915,  -7.765, -10.205,  -3.635,
200      -5.885,  -8.005, -10.505,  -4.395,  -7.325, -10.235,  -4.655,  -7.495, -10.515,   0.000 },
201   {  -2.705, -10.645,  -5.165, -10.095,  -4.995, -10.815,  -4.835, -10.385,  -4.835, -10.815,
202      -4.995, -10.095,  -5.165, -10.645,  -2.705,   0.000,   0.000,   0.000,   0.000,   0.000 },
203   { -10.515,  -7.495,  -4.655, -10.235,  -7.325,  -4.395, -10.505,  -8.005,  -5.885,  -3.635,
204     -10.205,  -7.765,  -5.915,  -3.975, -10.205,  -9.045,  -8.605,  -8.235,  -7.905,   0.000 },
205   {  -3.255,  -9.385,  -8.365, -10.355, -11.285,  -7.645,  -7.525,  -7.395,  -7.705,  -7.885,
206      -7.895,  -7.905,  -7.865,  -7.745,  -8.285,  -7.765,  -8.405, -10.885,  -8.405,   0.000 }
207 };
208 */
209
210
211 const Float_t AliTOFGeometry::fgkHeights[kNPlates][kMaxNstrip] = {
212   { -8.405,  -7.725,  -8.405,  -7.765,  -8.285,  -7.745,  -7.865,  -7.905,  -7.895,  -7.885,
213     -7.705,  -7.395,  -7.525,  -7.645,  -7.835,  -7.965,  -8.365,  -9.385,  -3.255,   0.000 },
214   { -7.905,  -8.235,  -8.605,  -9.045, -10.205,  -3.975,  -5.915,  -7.765, -10.205,  -3.635,
215     -5.885,  -8.005, -10.505,  -4.395,  -7.325, -10.235,  -4.655,  -7.495, -10.515,   0.000 },
216   { -2.705, -10.645,  -5.165, -10.095,  -4.995, -10.085,  -4.835, -10.385,  -4.835, -10.085,
217     -4.995, -10.095,  -5.165, -10.645,  -2.705,   0.000,   0.000,   0.000,   0.000,   0.000 },
218   {-10.515,  -7.495,  -4.655, -10.235,  -7.325,  -4.395, -10.505,  -8.005,  -5.885,  -3.635,
219    -10.205,  -7.765,  -5.915,  -3.975, -10.205,  -9.045,  -8.605,  -8.235,  -7.905,   0.000 },
220   { -3.255,  -9.385,  -8.365,  -7.965,  -7.835,  -7.645,  -7.525,  -7.395,  -7.705,  -7.885,
221     -7.895,  -7.905,  -7.865,  -7.745,  -8.285,  -7.765,  -8.405,  -7.725,  -8.405,   0.000 }
222 };
223
224
225
226 const Float_t AliTOFGeometry::fgkDistances[kNPlates][kMaxNstrip] = {
227   { 364.14,  354.88,  344.49,  335.31,  325.44,  316.51,  307.11,  297.91,  288.84,  279.89,
228     271.20,  262.62,  253.84,  245.20,  236.56,  228.06,  219.46,  210.63,  206.09,    0.00 },
229   { 194.57,  186.38,  178.25,  170.13,  161.78,  156.62,  148.10,  139.72,  131.23,  125.87,
230     117.61,  109.44,  101.29,   95.46,   87.36,   79.37,   73.17,   65.33,   57.71,    0.00 },
231   {  49.28,   41.35,   35.37,   27.91,   21.20,   13.94,    7.06,    0.00,   -7.06,  -13.94,
232     -21.20,  -27.91,  -35.37,  -41.35,  -49.28,    0.00,    0.00,    0.00,    0.00,    0.00 },
233   { -57.71,  -65.33,  -73.17,  -79.37,  -87.36,  -95.46, -101.29, -109.44, -117.61, -125.87,
234    -131.23, -139.72, -148.10, -156.62, -161.78, -170.13, -178.25, -186.38, -194.57,    0.00 },
235   {-206.09, -210.63, -219.46, -228.06, -236.56, -245.20, -253.84, -262.62, -271.20, -279.89,
236    -288.84, -297.91, -307.11, -316.51, -325.44, -335.31, -344.49, -354.88, -364.14,    0.00 }
237 };
238
239 /*
240 const Float_t AliTOFGeometry::fgkDistances[kNPlates][kMaxNstrip] = {
241     { 364.1,  354.9,  344.5,  335.4,  325.5,  316.6,  307.2,  298.0,  288.9,  280.0,
242       271.3,  262.7,  254.0,  244.8,  236.1,  227.7,  219.1,  210.3,  205.7,    0.0},
243
244     { 194.2,  186.1,  177.9,  169.8,  161.5,  156.3,  147.8,  139.4,  130.9,  125.6,
245       117.3,  109.2,  101.1,   95.3,   87.1,   79.2,   73.0,   65.1,   57.6,    0.0},
246
247     {  49.5,   41.3,   35.3,   27.8,   21.2,   13.9,    7.0,    0.0,   -7.0,  -13.9,
248       -21.2,  -27.8,  -35.3,  -41.3,  -49.5,    0.0,    0.0,    0.0,    0.0,    0.0},
249
250     { -57.6,  -65.1,  -73.0,  -79.2,  -87.1,  -95.3, -101.1, -109.2, -117.3, -125.6,
251      -130.9, -139.4, -147.8, -156.3, -161.5, -169.8, -177.9, -186.1, -194.2,    0.0},
252
253     {-205.7, -210.3, -219.1, -227.7, -236.1, -244.8, -254.0, -262.7, -271.3, -280.0,
254      -288.9, -298.0, -307.2, -316.6, -325.5, -335.4, -344.5, -354.9, -364.1,    0.0}
255   };
256 */
257 //_____________________________________________________________________________
258 AliTOFGeometry::AliTOFGeometry():
259   fHoles(1)
260 {
261   //
262   // AliTOFGeometry default constructor
263   //
264
265 }
266
267 //_____________________________________________________________________________
268 AliTOFGeometry::~AliTOFGeometry()
269 {
270   //
271   // AliTOFGeometry destructor
272   //
273 }
274 //_____________________________________________________________________________
275 void AliTOFGeometry::ImportGeometry(){
276   TGeoManager::Import("geometry.root");
277 }
278 //_____________________________________________________________________________
279 void AliTOFGeometry::GetPosPar(Int_t *det, Float_t *pos) const
280 {
281 //
282 // Returns space point coor (x,y,z) (cm)  for Detector 
283 // Indices  (iSect,iPlate,iStrip,iPadX,iPadZ) 
284 //
285
286   pos[0]=GetX(det);  
287   pos[1]=GetY(det);  
288   pos[2]=GetZ(det);
289   
290 }
291 //_____________________________________________________________________________
292 void AliTOFGeometry::GetDetID( Float_t *pos, Int_t *det) const
293 {
294  //
295  // Returns Detector Indices (iSect,iPlate,iStrip,iPadX,iPadZ) 
296  // space point coor (x,y,z) (cm)  
297
298
299   det[0]=GetSector(pos);  
300   det[1]=GetPlate(pos);  
301   det[2]=GetStrip(pos);
302   det[3]=GetPadZ(pos);
303   det[4]=GetPadX(pos);
304   
305 }
306 //_____________________________________________________________________________
307
308 void AliTOFGeometry::DetToStripRF(Int_t nPadX, Int_t nPadZ, Float_t &x,  Float_t &z) const
309 {
310   //
311   // Returns the local coordinates (x, z) in strip reference frame
312   // for the bottom corner of the pad number (nPadX, nPadZ)
313   //
314   /*
315   const Float_t xCenterStrip = kNpadX * fgkXPad / 2.;
316   const Float_t zCenterStrip = kNpadZ * fgkZPad / 2.;
317
318   const Float_t xCenterPad = nPadX*fgkXPad + fgkXPad / 2.;
319   const Float_t zCenterPad = nPadZ*fgkZPad + fgkZPad / 2.;
320
321   x = xCenterPad - xCenterStrip;
322   z = zCenterPad - zCenterStrip;
323   */
324
325
326   x = (nPadX - kNpadX*0.5) * fgkXPad;
327   z = (nPadZ - kNpadZ*0.5) * fgkZPad;
328
329
330 }
331 //_____________________________________________________________________________
332 Float_t AliTOFGeometry::DistanceToPadPar(Int_t *det, const Float_t * const pos, Float_t *dist3d) const
333 {
334 //
335 // Returns distance of  space point with coor pos (x,y,z) (cm) wrt 
336 // pad with Detector Indices idet (iSect,iPlate,iStrip,iPadX,iPadZ) 
337 //
338     
339   //Transform pos into Sector Frame
340
341   Float_t x = pos[0];
342   Float_t y = pos[1];
343   Float_t z = pos[2];
344
345   Float_t radius = TMath::Sqrt(x*x+y*y);
346   //Float_t phi=TMath::ATan(y/x);       
347   //if(phi<0) phi = k2PI+phi; //2.*TMath::Pi()+phi;
348   Float_t phi = TMath::Pi()+TMath::ATan2(-y,-x);        
349   //  Get the local angle in the sector philoc
350   Float_t angle   = phi*kRaddeg-( Int_t (kRaddeg*phi/fgkPhiSec) + 0.5)*fgkPhiSec;
351   Float_t xs = radius*TMath::Cos(angle/kRaddeg);
352   Float_t ys = radius*TMath::Sin(angle/kRaddeg);
353   Float_t zs = z;
354
355   // Do the same for the selected pad
356
357   Float_t g[3];
358   GetPosPar(det,g);
359
360   Float_t padRadius = TMath::Sqrt(g[0]*g[0]+g[1]*g[1]);
361   //Float_t padPhi = TMath::ATan(g[1]/g[0]);    
362   //if(padPhi<0) padPhi = k2Pi + padPhi;
363   Float_t padPhi = TMath::Pi()+TMath::ATan2(-g[1],-g[0]);       
364
365   //  Get the local angle in the sector philoc
366   Float_t padAngle = padPhi*kRaddeg-( Int_t (padPhi*kRaddeg/fgkPhiSec)+ 0.5) * fgkPhiSec;
367   Float_t padxs = padRadius*TMath::Cos(padAngle/kRaddeg);
368   Float_t padys = padRadius*TMath::Sin(padAngle/kRaddeg);
369   Float_t padzs = g[2];
370   
371   //Now move to local pad coordinate frame. Translate:
372   
373   Float_t xt = xs-padxs;
374   Float_t yt = ys-padys;
375   Float_t zt = zs-padzs;
376   //Now Rotate:
377   
378   Float_t alpha = GetAngles(det[1],det[2]);
379   Float_t xr =  xt*TMath::Cos(alpha/kRaddeg)+zt*TMath::Sin(alpha/kRaddeg);
380   Float_t yr =  yt;
381   Float_t zr = -xt*TMath::Sin(alpha/kRaddeg)+zt*TMath::Cos(alpha/kRaddeg);
382
383   Float_t dist = TMath::Sqrt(xr*xr+yr*yr+zr*zr);
384
385   if (dist3d){
386     dist3d[0] = xr;
387     dist3d[1] = yr;
388     dist3d[2] = zr;
389   }
390
391   return dist;
392
393 }
394 //_____________________________________________________________________________
395 Bool_t AliTOFGeometry::IsInsideThePadPar(Int_t *det, const Float_t * const pos) const
396 {
397 //
398 // Returns true if space point with coor pos (x,y,z) (cm) falls 
399 // inside pad with Detector Indices idet (iSect,iPlate,iStrip,iPadX,iPadZ) 
400 //
401
402   Bool_t isInside=false; 
403
404   /*
405   const Float_t khhony    = 1.0          ; // heigth of HONY  Layer
406   const Float_t khpcby    = 0.08         ; // heigth of PCB   Layer
407   const Float_t khrgly    = 0.055        ; // heigth of RED GLASS  Layer
408   const Float_t khglfy    = 0.285        ; // heigth of GLASS+FISHLINE  Layer
409   const Float_t khcpcby   = 0.16         ; // heigth of PCB  Central Layer
410   //const Float_t kwcpcbz   = 12.4         ; // z dimension of PCB  Central Layer
411   const Float_t khstripy = 2.*khhony+2.*khpcby+4.*khrgly+2.*khglfy+khcpcby;//3.11
412   //const Float_t kwstripz = kwcpcbz;
413   //const Float_t klstripx = fgkStripLength;
414   */
415
416   const Float_t kPadDepth = 0.5;//0.05;//0.11;//0.16;//          // heigth of Sensitive Layer
417
418   //Transform pos into Sector Frame
419
420   Float_t x = pos[0];
421   Float_t y = pos[1];
422   Float_t z = pos[2];
423
424   Float_t radius = TMath::Sqrt(x*x+y*y);
425   Float_t phi = TMath::Pi()+TMath::ATan2(-y,-x);        
426
427   //  Get the local angle in the sector philoc
428   Float_t angle = phi*kRaddeg-( Int_t (kRaddeg*phi/fgkPhiSec) + 0.5) *fgkPhiSec;
429   Float_t xs = radius*TMath::Cos(angle/kRaddeg);
430   Float_t ys = radius*TMath::Sin(angle/kRaddeg);
431   Float_t zs = z;
432
433   // Do the same for the selected pad
434
435   Float_t g[3];
436   GetPosPar(det,g);
437
438   Float_t padRadius = TMath::Sqrt(g[0]*g[0]+g[1]*g[1]);
439   Float_t padPhi = TMath::Pi()+TMath::ATan2(-g[1],-g[0]);       
440
441   //  Get the local angle in the sector philoc
442   Float_t padAngle = padPhi*kRaddeg-( Int_t (padPhi*kRaddeg/fgkPhiSec)+ 0.5) * fgkPhiSec; 
443   Float_t padxs = padRadius*TMath::Cos(padAngle/kRaddeg);
444   Float_t padys = padRadius*TMath::Sin(padAngle/kRaddeg);
445   Float_t padzs = g[2];
446
447   //Now move to local pad coordinate frame. Translate:
448
449   Float_t xt = xs-padxs;
450   Float_t yt = ys-padys;
451   Float_t zt = zs-padzs;
452
453   //Now Rotate:
454
455   Float_t alpha = GetAngles(det[1],det[2]);
456   Float_t xr =  xt*TMath::Cos(alpha/kRaddeg)+zt*TMath::Sin(alpha/kRaddeg);
457   Float_t yr =  yt;
458   Float_t zr = -xt*TMath::Sin(alpha/kRaddeg)+zt*TMath::Cos(alpha/kRaddeg);
459
460   if(TMath::Abs(xr)<=kPadDepth*0.5 && TMath::Abs(yr)<= (fgkXPad*0.5) && TMath::Abs(zr)<= (fgkZPad*0.5))
461     isInside=true;
462   return isInside;
463
464 }
465 //_____________________________________________________________________________
466 Bool_t AliTOFGeometry::IsInsideThePad(TGeoHMatrix *mat, const Float_t * const pos, Float_t *dist3d) const
467 {
468   //
469   // Returns true if space point with coor pos (x,y,z) [cm] falls inside
470   // pad identified by the matrix mat. In case dist3d!=0, dist3d vector
471   // has been filled with the 3D distance between the impact point on
472   // the pad and the pad centre (in the reference frame of the TOF pad
473   // identified by the matrix mat).
474   //
475
476   const Float_t kPadDepth = 0.5;      // heigth of Sensitive Layer
477
478   Double_t posg[3];
479   posg[0] = pos[0];
480   posg[1] = pos[1];
481   posg[2] = pos[2];
482
483   // from ALICE global reference system
484   // towards TOF pad reference system
485   Double_t posl[3] = {0., 0., 0.};
486   mat->MasterToLocal(posg,posl);
487
488   Float_t xr = posl[0];
489   Float_t yr = posl[1];
490   Float_t zr = posl[2];
491
492   Bool_t isInside = false;
493   if (TMath::Abs(yr)<= kPadDepth*0.5 &&
494       TMath::Abs(xr)<= fgkXPad*0.5 &&
495       TMath::Abs(zr)<= fgkZPad*0.5)
496     isInside = true;
497
498   if (dist3d) {
499     //Double_t padl[3] = {0., 0., 0.};
500     dist3d[0] = posl[0]/* - padl[0]*/;
501     dist3d[1] = posl[1]/* - padl[1]*/;
502     dist3d[2] = posl[2]/* - padl[2]*/;
503
504     /*
505     Double_t padg[3] = {0., 0., 0.};
506     // from TOF pad local reference system
507     // towards ALICE global reference system
508     TGeoHMatrix inverse = mat->Inverse();
509     inverse.MasterToLocal(padl,padg);
510
511     // returns the 3d distance
512     // between the impact point on the pad
513     // and the pad centre (in the ALICE global reference frame)
514     dist3d[0] = posg[0] - padg[0];
515     dist3d[1] = posg[1] - padg[1];
516     dist3d[2] = posg[2] - padg[2];
517     */
518   }
519  
520   return isInside;
521
522 }
523 //_____________________________________________________________________________
524 void AliTOFGeometry::GetVolumePath(const Int_t * const ind, Char_t *path ) {
525   //--------------------------------------------------------------------
526   // This function returns the colume path of a given pad 
527   //--------------------------------------------------------------------
528   Int_t sector = ind[0];
529
530   const Int_t kSize = 100;
531
532   Char_t  string1[kSize];
533   Char_t  string2[kSize];
534   Char_t  string3[kSize];
535   
536   Int_t icopy=-1;
537   icopy=sector;
538  
539   snprintf(string1,kSize,"/ALIC_1/B077_1/BSEGMO%i_1/BTOF%i_1",icopy,icopy);
540   
541   Int_t iplate=ind[1];
542   Int_t istrip=ind[2];
543   if( iplate==0) icopy=istrip; 
544   if( iplate==1) icopy=istrip+NStripC(); 
545   if( iplate==2) icopy=istrip+NStripC()+NStripB(); 
546   if( iplate==3) icopy=istrip+NStripC()+NStripB()+NStripA(); 
547   if( iplate==4) icopy=istrip+NStripC()+2*NStripB()+NStripA(); 
548   icopy++;
549   snprintf(string2,kSize,"FTOA_0/FLTA_0/FSTR_%i",icopy);
550   if(fHoles && (sector==13 || sector==14 || sector==15)){
551     if(iplate<2)  snprintf(string2,kSize,"FTOB_0/FLTB_0/FSTR_%i",icopy);
552     if(iplate>2)  snprintf(string2,kSize,"FTOC_0/FLTC_0/FSTR_%i",icopy);
553   }
554  
555   Int_t padz = ind[3]+1; 
556   Int_t padx = ind[4]+1;
557   snprintf(string3,kSize,"FPCB_1/FSEN_1/FSEZ_%i/FPAD_%i",padz,padx);
558   snprintf(path,2*kSize,"%s/%s/%s",string1,string2,string3); 
559
560 }
561 //_____________________________________________________________________________
562 void AliTOFGeometry::GetVolumePath(Int_t sector, Char_t *path ){
563   //--------------------------------------------------------------------
564   // This function returns the colume path of a given sector 
565   //--------------------------------------------------------------------
566
567   const Int_t kSize = 100;
568
569   Char_t string[kSize];
570
571   Int_t icopy = sector;
572
573   snprintf(string,kSize,"/ALIC_1/B077_1/BSEGMO%i_1/BTOF%i_1",icopy,icopy);
574   snprintf(path,2*kSize,"%s",string);
575
576 }
577 //_____________________________________________________________________________
578 void AliTOFGeometry::GetVolumePath(Int_t sector, Int_t plate, Int_t strip, Char_t *path ) {
579   //--------------------------------------------------------------------
580   // This function returns the colume path of a given strip 
581   //--------------------------------------------------------------------
582
583   const Int_t kSize = 100;
584
585   Char_t string1[kSize];
586   Char_t string2[kSize];
587   Char_t string3[kSize];
588   
589   Int_t icopy = sector;
590
591   snprintf(string1,kSize,"/ALIC_1/B077_1/BSEGMO%i_1/BTOF%i_1",icopy,icopy);
592   
593   if(plate==0) icopy=strip; 
594   if(plate==1) icopy=strip+NStripC(); 
595   if(plate==2) icopy=strip+NStripC()+NStripB(); 
596   if(plate==3) icopy=strip+NStripC()+NStripB()+NStripA(); 
597   if(plate==4) icopy=strip+NStripC()+2*NStripB()+NStripA(); 
598   icopy++;
599   snprintf(string2,kSize,"FTOA_0/FLTA_0/FSTR_%i",icopy);
600   if(fHoles && (sector==13 || sector==14 || sector==15)){
601     if(plate<2)  snprintf(string2,kSize,"FTOB_0/FLTB_0/FSTR_%i",icopy);
602     if(plate>2)  snprintf(string2,kSize,"FTOC_0/FLTC_0/FSTR_%i",icopy);
603   }
604
605   snprintf(string3,kSize,"FPCB_1/FSEN_1");
606   snprintf(path,2*kSize,"%s/%s/%s",string1,string2,string3); 
607
608 }
609 //_____________________________________________________________________________
610 void AliTOFGeometry::GetPos(Int_t *det, Float_t *pos) 
611 {
612 //
613 // Returns space point coor (x,y,z) (cm)  for Detector 
614 // Indices  (iSect,iPlate,iStrip,iPadX,iPadZ) 
615 //
616   Char_t path[200];
617   GetVolumePath(det,path);
618   if (!gGeoManager) {
619     printf("ERROR: no TGeo\n");
620   }
621   gGeoManager->cd(path);
622   TGeoHMatrix global;
623   global = *gGeoManager->GetCurrentMatrix();
624   const Double_t *tr = global.GetTranslation();
625
626   pos[0]=tr[0];  
627   pos[1]=tr[1];  
628   pos[2]=tr[2];
629 }
630 //_____________________________________________________________________________
631 Int_t AliTOFGeometry::GetPlate(const Float_t * const pos) const
632 {
633   //
634   // Returns the Plate index 
635   //
636   const Float_t kInterCentrModBorder1 = 49.5;
637   const Float_t kInterCentrModBorder2 = 57.5;
638   const Float_t kExterInterModBorder1 = 196.0;
639   const Float_t kExterInterModBorder2 = 203.5;
640
641   const Float_t kLengthExInModBorder  = 4.7;
642   const Float_t kLengthInCeModBorder  = 7.0;
643
644   //const Float_t khAlWall = 0.1;
645   const Float_t kModuleWallThickness = 0.3;
646   //const Float_t kHoneycombLayerThickness = 1.5;
647
648   Int_t iPlate=-1;
649
650   Float_t posLocal[3];
651   for (Int_t ii=0; ii<3; ii++) posLocal[ii] = pos[ii];
652
653   Int_t isector = GetSector(posLocal);
654   if(isector == -1){
655     //AliError("Detector Index could not be determined");
656     return iPlate;
657   }
658
659   // ALICE reference frame -> B071/B074/B075 = BTO1/2/3 reference frame
660   Double_t angles[6] = 
661     {90., 90.+(isector+0.5)*fgkPhiSec,
662       0., 0.,
663      90., (isector+0.5)*fgkPhiSec
664     };
665   Rotation(posLocal,angles);
666
667   Float_t step[3] = {0., 0., (fgkRmax+fgkRmin)*0.5};
668   Translation(posLocal,step);
669
670   // B071/B074/B075 = BTO1/2/3 reference frame -> FTOA = FLTA reference frame
671   angles[0] = 90.;
672   angles[1] =  0.;
673   angles[2] =  0.;
674   angles[3] =  0.;
675   angles[4] = 90.;
676   angles[5] =270.;
677
678   Rotation(posLocal,angles);
679
680   Float_t yLocal = posLocal[1];
681   Float_t zLocal = posLocal[2];
682
683   Float_t deltaRhoLoc  = (fgkRmax-fgkRmin)*0.5 - kModuleWallThickness + yLocal;
684   Float_t deltaZetaLoc = TMath::Abs(zLocal);
685
686   Float_t deltaRHOmax = 0.;
687
688   if (TMath::Abs(zLocal)>=kExterInterModBorder1 && TMath::Abs(zLocal)<=kExterInterModBorder2) 
689     {
690       deltaRhoLoc -= kLengthExInModBorder;
691       deltaZetaLoc = kExterInterModBorder2-deltaZetaLoc;
692       deltaRHOmax  = (fgkRmax - fgkRmin)*0.5 - kModuleWallThickness - 2.*kLengthExInModBorder; // old 5.35, new 4.8
693
694       if (deltaRhoLoc > deltaZetaLoc*deltaRHOmax/(kInterCentrModBorder2-kInterCentrModBorder1)) {
695         if (zLocal<0) iPlate = 0;
696         else iPlate = 4;
697       }
698       else {
699         if (zLocal<0) iPlate = 1;
700         else iPlate = 3;
701       }
702     }
703   else if (TMath::Abs(zLocal)>=kInterCentrModBorder1 && TMath::Abs(zLocal)<=kInterCentrModBorder2) 
704     {
705       deltaRhoLoc -= kLengthInCeModBorder;
706       deltaZetaLoc = deltaZetaLoc-kInterCentrModBorder1;
707       deltaRHOmax = (fgkRmax - fgkRmin)*0.5 - kModuleWallThickness - 2.*kLengthInCeModBorder; // old 0.39, new 0.2
708
709       if (deltaRhoLoc>deltaZetaLoc*deltaRHOmax/(kInterCentrModBorder2-kInterCentrModBorder1)) iPlate = 2;
710       else {
711         if (zLocal<0) iPlate = 1;
712         else iPlate = 3;
713       }
714     }
715
716   if      (zLocal>-fgkZlenA*0.5          && zLocal<-kExterInterModBorder2) iPlate = 0;
717   else if (zLocal>-kExterInterModBorder1 && zLocal<-kInterCentrModBorder2) iPlate = 1;
718   else if (zLocal>-kInterCentrModBorder1 && zLocal< kInterCentrModBorder1) iPlate = 2;
719   else if (zLocal> kInterCentrModBorder2 && zLocal< kExterInterModBorder1) iPlate = 3;
720   else if (zLocal> kExterInterModBorder2 && zLocal< fgkZlenA*0.5)          iPlate = 4;
721   
722   return iPlate;
723
724 }
725
726 //_____________________________________________________________________________
727 Int_t AliTOFGeometry::GetSector(const Float_t * const pos) const
728 {
729   //
730   // Returns the Sector index 
731   //
732
733   Int_t   iSect = -1; 
734
735   Float_t x = pos[0];
736   Float_t y = pos[1];
737   Float_t z = pos[2];
738
739   Float_t rho = TMath::Sqrt(x*x + y*y);
740
741   if (!((z>=-fgkZlenA*0.5 && z<=fgkZlenA*0.5) &&
742         (rho>=(fgkRmin) && rho<=(fgkRmax)))) {
743     //AliError("Detector Index could not be determined");
744     return iSect;
745   }
746
747   Float_t phi = TMath::Pi() + TMath::ATan2(-y,-x);      
748
749   iSect  = (Int_t) (phi*kRaddeg/fgkPhiSec);
750   
751   return iSect;
752
753 }
754 //_____________________________________________________________________________
755 Int_t AliTOFGeometry::GetStrip(const Float_t * const pos) const
756 {
757   //
758   // Returns the Strip index 
759   //
760   const Float_t khhony    = 1.0          ; // heigth of HONY  Layer
761   const Float_t khpcby    = 0.08         ; // heigth of PCB   Layer
762   const Float_t khrgly    = 0.055        ; // heigth of RED GLASS  Layer
763   const Float_t khglfy    = 0.285        ; // heigth of GLASS+FISHLINE  Layer
764   const Float_t khcpcby   = 0.16         ; // heigth of PCB  Central Layer
765   const Float_t kwcpcbz   = 12.4         ; // z dimension of PCB  Central Layer
766   const Float_t khstripy = 2.*khhony+2.*khpcby+4.*khrgly+2.*khglfy+khcpcby;//3.11
767   const Float_t kwstripz = kwcpcbz;
768   const Float_t klstripx = fgkStripLength;
769   
770   Int_t iStrip=-1;
771    
772   Float_t posLocal[3];
773   for (Int_t ii=0; ii<3; ii++) posLocal[ii] = pos[ii];
774   AliDebug(1,Form("  posLocal[0] = %f, posLocal[1] = %f, posLocal[2] = %f ",
775                   posLocal[0],posLocal[1],posLocal[2]));
776
777   Int_t isector = GetSector(posLocal);
778   if(isector == -1){
779     //AliError("Detector Index could not be determined");
780     return iStrip;}
781   Int_t iplate =  GetPlate(posLocal);
782   if(iplate == -1){
783     //AliError("Detector Index could not be determined");
784     return iStrip;} 
785
786   Int_t nstrips=0;
787   switch (iplate) {
788   case 0:
789   case 4:
790     nstrips=kNStripC;
791     break;
792   case 1:
793   case 3:
794     nstrips=kNStripB;
795     break;
796   case 2:
797     nstrips=kNStripA;
798     break;
799   }
800   
801   // ALICE reference frame -> B071/B074/B075 = BTO1/2/3 reference frame
802   Double_t angles[6] = 
803     {90., 90.+(isector+0.5)*fgkPhiSec,
804       0., 0.,
805      90., (isector+0.5)*fgkPhiSec
806     };
807   Rotation(posLocal,angles);
808   AliDebug(1,Form("  posLocal[0] = %f, posLocal[1] = %f, posLocal[2] = %f ",
809                   posLocal[0],posLocal[1],posLocal[2]));
810
811   Float_t step[3] = {0., 0., (fgkRmax+fgkRmin)*0.5};
812   Translation(posLocal,step);
813   AliDebug(1,Form("  posLocal[0] = %f, posLocal[1] = %f, posLocal[2] = %f ",
814                   posLocal[0],posLocal[1],posLocal[2]));
815
816   // B071/B074/B075 = BTO1/2/3 reference frame -> FTOA = FLTA reference frame
817   angles[0] = 90.;
818   angles[1] =  0.;
819   angles[2] =  0.;
820   angles[3] =  0.;
821   angles[4] = 90.;
822   angles[5] =270.;
823
824   Rotation(posLocal,angles);
825   AliDebug(1,Form("  posLocal[0] = %f, posLocal[1] = %f, posLocal[2] = %f ",
826                   posLocal[0],posLocal[1],posLocal[2]));
827
828   // FTOA/B/C = FLTA/B/C reference frame -> FSTR reference frame
829   Int_t totStrip=0;
830   for (Int_t istrip=0; istrip<nstrips; istrip++){
831
832     Float_t posLoc2[3]={posLocal[0],posLocal[1],posLocal[2]};         
833
834     step[0] = 0.;
835     step[1] = GetHeights(iplate,istrip);
836     step[2] = -GetDistances(iplate,istrip);
837     Translation(posLoc2,step);
838
839     if      (GetAngles(iplate,istrip) >0.) {
840       angles[0] = 90.;
841       angles[1] =  0.;
842       angles[2] = 90.+GetAngles(iplate,istrip);
843       angles[3] = 90.;
844       angles[4] = GetAngles(iplate,istrip);
845       angles[5] = 90.;
846     }
847     else if (GetAngles(iplate,istrip)==0.) {
848       angles[0] = 90.;
849       angles[1] =  0.;
850       angles[2] = 90.;
851       angles[3] = 90.;
852       angles[4] =  0;
853       angles[5] =  0.;
854     }
855     else if (GetAngles(iplate,istrip) <0.) {
856       angles[0] = 90.;
857       angles[1] =  0.;
858       angles[2] = 90.+GetAngles(iplate,istrip);
859       angles[3] = 90.;
860       angles[4] =-GetAngles(iplate,istrip);
861       angles[5] = 270.;
862     }
863     Rotation(posLoc2,angles);
864     AliDebug(1,Form(" strip %2d:  posLoc2[0] = %f, posLoc2[1] = %f, posLoc2[2] = %f ",
865                     istrip, posLoc2[0],posLoc2[1],posLoc2[2]));
866
867     if ((TMath::Abs(posLoc2[0])<=klstripx*0.5) &&
868         (TMath::Abs(posLoc2[1])<=khstripy*0.5) &&
869         (TMath::Abs(posLoc2[2])<=kwstripz*0.5)) {
870       iStrip = istrip;
871       totStrip++;
872       for (Int_t jj=0; jj<3; jj++) posLocal[jj]=posLoc2[jj];
873       AliDebug(2,Form(" posLocal[0] = %f, posLocal[1] = %f, posLocal[2] = %f ",
874                       posLocal[0],posLocal[1],posLocal[2]));
875
876       AliDebug(2,Form(" GetAngles(%1i,%2i) = %f, pos[0] = %f, pos[1] = %f, pos[2] = %f",
877                       iplate, istrip, GetAngles(iplate,istrip), pos[0], pos[1], pos[2]));
878       break;
879     }
880
881     if (totStrip>1) AliInfo(Form("total strip number found %2i",totStrip));
882
883   }
884
885   return iStrip;
886   
887 }
888 //_____________________________________________________________________________
889 Int_t AliTOFGeometry::GetPadZ(const Float_t * const pos) const
890 {
891   //
892   // Returns the Pad index along Z 
893   //
894   //const Float_t klsensmx = kNpadX*fgkXPad;  // length of Sensitive Layer
895   //const Float_t khsensmy = 0.05;//0.11;//0.16;// heigth of Sensitive Layer
896   //const Float_t kwsensmz = kNpadZ*fgkZPad;  // width of Sensitive Layer
897
898   Int_t iPadZ = -1;
899
900   Float_t posLocal[3];
901   for (Int_t ii=0; ii<3; ii++) posLocal[ii] = pos[ii];
902  
903   Int_t isector = GetSector(posLocal);
904   if(isector == -1){
905     //AliError("Detector Index could not be determined");
906     return iPadZ;}
907   Int_t iplate =  GetPlate(posLocal);
908   if(iplate == -1){
909     //AliError("Detector Index could not be determined");
910     return iPadZ;}
911   Int_t istrip =  GetStrip(posLocal);
912   if(istrip == -1){
913     //AliError("Detector Index could not be determined");
914     return iPadZ;}
915
916   // ALICE reference frame -> B071/B074/B075 = BTO1/2/3 reference frame
917   Double_t angles[6] = 
918     {90., 90.+(isector+0.5)*fgkPhiSec,
919       0., 0.,
920      90., (isector+0.5)*fgkPhiSec
921     };
922   Rotation(posLocal,angles);
923
924   Float_t step[3] = {0., 0., (fgkRmax+fgkRmin)*0.5};
925   Translation(posLocal,step);
926
927   // B071/B074/B075 = BTO1/2/3 reference frame -> FTOA = FLTA reference frame
928   angles[0] = 90.;
929   angles[1] =  0.;
930   angles[2] =  0.;
931   angles[3] =  0.;
932   angles[4] = 90.;
933   angles[5] =270.;
934
935   Rotation(posLocal,angles);
936
937   // FTOA/B/C = FLTA/B/C reference frame -> FSTR reference frame
938   step[0] = 0.;
939   step[1] = GetHeights(iplate,istrip);
940   step[2] = -GetDistances(iplate,istrip);
941   Translation(posLocal,step);
942
943   if      (GetAngles(iplate,istrip) >0.) {
944     angles[0] = 90.;
945     angles[1] =  0.;
946     angles[2] = 90.+GetAngles(iplate,istrip);
947     angles[3] = 90.;
948     angles[4] = GetAngles(iplate,istrip);
949     angles[5] = 90.;
950   }
951   else if (GetAngles(iplate,istrip)==0.) {
952     angles[0] = 90.;
953     angles[1] =  0.;
954     angles[2] = 90.;
955     angles[3] = 90.;
956     angles[4] =  0;
957     angles[5] =  0.;
958   }
959   else if (GetAngles(iplate,istrip) <0.) {
960     angles[0] = 90.;
961     angles[1] =  0.;
962     angles[2] = 90.+GetAngles(iplate,istrip);
963     angles[3] = 90.;
964     angles[4] =-GetAngles(iplate,istrip);
965     angles[5] = 270.;
966   }
967   Rotation(posLocal,angles);
968
969   step[0] =-0.5*kNpadX*fgkXPad;
970   step[1] = 0.;
971   step[2] =-0.5*kNpadZ*fgkZPad;
972   Translation(posLocal,step);
973
974   iPadZ = (Int_t)(posLocal[2]/fgkZPad);
975   if (iPadZ==kNpadZ) iPadZ--;
976   else if (iPadZ>kNpadZ) iPadZ=-1;
977
978   return iPadZ;
979
980 }
981 //_____________________________________________________________________________
982 Int_t AliTOFGeometry::GetPadX(const Float_t * const pos) const
983 {
984   //
985   // Returns the Pad index along X 
986   //
987   //const Float_t klsensmx = kNpadX*fgkXPad;  // length of Sensitive Layer
988   //const Float_t khsensmy = 0.05;//0.11;//0.16;// heigth of Sensitive Layer
989   //const Float_t kwsensmz = kNpadZ*fgkZPad;  // width of Sensitive Layer
990
991   Int_t iPadX  = -1;
992
993   Float_t posLocal[3];
994   for (Int_t ii=0; ii<3; ii++) posLocal[ii] = pos[ii];
995  
996   Int_t isector = GetSector(posLocal);
997   if(isector == -1){
998     //AliError("Detector Index could not be determined");
999     return iPadX;}
1000   Int_t iplate =  GetPlate(posLocal);
1001   if(iplate == -1){
1002     //AliError("Detector Index could not be determined");
1003     return iPadX;} 
1004   Int_t istrip =  GetStrip(posLocal);
1005   if(istrip == -1){  
1006     //AliError("Detector Index could not be determined");
1007     return iPadX;}
1008
1009   // ALICE reference frame -> B071/B074/B075 = BTO1/2/3 reference frame
1010   Double_t angles[6] = 
1011     {90., 90.+(isector+0.5)*fgkPhiSec,
1012       0.,  0.,
1013      90., (isector+0.5)*fgkPhiSec
1014     };
1015   Rotation(posLocal,angles);
1016
1017   Float_t step[3] = {0., 0., (fgkRmax+fgkRmin)*0.5};
1018   Translation(posLocal,step);
1019
1020   // B071/B074/B075 = BTO1/2/3 reference frame -> FTOA/B/C = FLTA/B/C reference frame
1021   angles[0] = 90.;
1022   angles[1] =  0.;
1023   angles[2] =  0.;
1024   angles[3] =  0.;
1025   angles[4] = 90.;
1026   angles[5] =270.;
1027
1028   Rotation(posLocal,angles);
1029
1030   // FTOA/B/C = FLTA/B/C reference frame -> FSTR reference frame
1031   step[0] = 0.;
1032   step[1] = GetHeights(iplate,istrip);
1033   step[2] = -GetDistances(iplate,istrip);
1034   Translation(posLocal,step);
1035
1036   if      (GetAngles(iplate,istrip) >0.) {
1037     angles[0] = 90.;
1038     angles[1] =  0.;
1039     angles[2] = 90.+GetAngles(iplate,istrip);
1040     angles[3] = 90.;
1041     angles[4] = GetAngles(iplate,istrip);
1042     angles[5] = 90.;
1043   }
1044   else if (GetAngles(iplate,istrip)==0.) {
1045     angles[0] = 90.;
1046     angles[1] =  0.;
1047     angles[2] = 90.;
1048     angles[3] = 90.;
1049     angles[4] =  0;
1050     angles[5] =  0.;
1051   }
1052   else if (GetAngles(iplate,istrip) <0.) {
1053     angles[0] = 90.;
1054     angles[1] =  0.;
1055     angles[2] = 90.+GetAngles(iplate,istrip);
1056     angles[3] = 90.;
1057     angles[4] =-GetAngles(iplate,istrip);
1058     angles[5] = 270.;
1059   }
1060   Rotation(posLocal,angles);
1061
1062   step[0] =-0.5*kNpadX*fgkXPad;
1063   step[1] = 0.;
1064   step[2] =-0.5*kNpadZ*fgkZPad;
1065   Translation(posLocal,step);
1066
1067   iPadX = (Int_t)(posLocal[0]/fgkXPad);
1068   if (iPadX==kNpadX) iPadX--;
1069   else if (iPadX>kNpadX) iPadX=-1;
1070
1071   return iPadX;
1072
1073 }
1074 //_____________________________________________________________________________
1075 Float_t AliTOFGeometry::GetX(const Int_t * const det) const
1076 {
1077   //
1078   // Returns X coordinate (cm)
1079   //
1080
1081   Int_t isector = det[0];
1082   Int_t iplate  = det[1];
1083   Int_t istrip  = det[2];
1084   Int_t ipadz   = det[3];
1085   Int_t ipadx   = det[4];
1086
1087   /*
1088   // Find out distance d on the plane wrt median phi:
1089   Float_t d = (ipadx+0.5-kNpadX*0.5)*fgkXPad;
1090
1091   // The radius r in xy plane:
1092   //Float_t r = (fgkRmin+fgkRmax)*0.5-0.01+GetHeights(iplate,istrip)+
1093   //  (ipadz-0.5)*fgkZPad*TMath::Sin(GetAngles(iplate,istrip)/kRaddeg)-0.25; ???
1094   Float_t r = (fgkRmin+fgkRmax)*0.5-0.01+GetHeights(iplate,istrip)+
1095     (ipadz-0.5)*fgkZPad*TMath::Sin(GetAngles(iplate,istrip)/kRaddeg);
1096
1097   // local azimuthal angle in the sector philoc
1098   Float_t philoc  = TMath::ATan(d/r);
1099   //if(philoc<0.) philoc = k2PI + philoc;
1100
1101   // azimuthal angle in the global frame  phi
1102   Float_t phi   = philoc*kRaddeg+(isector+0.5)*fgkPhiSec;
1103
1104   Float_t xCoor = r/TMath::Cos(philoc)*TMath::Cos(phi/kRaddeg);
1105   */
1106
1107   // Pad reference frame -> FSTR reference frame
1108   Float_t posLocal[3] = {0., 0., 0.};
1109   Float_t step[3] = {-(ipadx+0.5)*fgkXPad, 0., -(ipadz+0.5)*fgkZPad};
1110   Translation(posLocal,step);
1111
1112   step[0] = kNpadX*0.5*fgkXPad;
1113   step[1] = 0.;
1114   step[2] = kNpadZ*0.5*fgkZPad;
1115   /*
1116   Float_t posLocal[3] = {(ipadx+0.5)*fgkXPad, 0., (ipadz+0.5)*fgkZPad};
1117   Float_t step[3]= {kNpadX*0.5*fgkXPad, 0., kNpadZ*0.5*fgkZPad};
1118   */
1119   Translation(posLocal,step);
1120
1121   // FSTR reference frame -> FTOA/B/C = FLTA/B/C reference frame
1122   Double_t angles[6] = {0.,0.,0.,0.,0.,0.};
1123   if      (GetAngles(iplate,istrip) >0.) {
1124     angles[0] = 90.;
1125     angles[1] =  0.;
1126     angles[2] = 90.+GetAngles(iplate,istrip);
1127     angles[3] = 90.;
1128     angles[4] = GetAngles(iplate,istrip);
1129     angles[5] = 90.;
1130   }
1131   else if (GetAngles(iplate,istrip)==0.) {
1132     angles[0] = 90.;
1133     angles[1] =  0.;
1134     angles[2] = 90.;
1135     angles[3] = 90.;
1136     angles[4] =  0;
1137     angles[5] =  0.;
1138   }
1139   else if (GetAngles(iplate,istrip) <0.) {
1140     angles[0] = 90.;
1141     angles[1] =  0.;
1142     angles[2] = 90.+GetAngles(iplate,istrip);
1143     angles[3] = 90.;
1144     angles[4] =-GetAngles(iplate,istrip);
1145     angles[5] = 270.;
1146   }
1147
1148   InverseRotation(posLocal,angles);
1149
1150   step[0] = 0.;
1151   step[1] = -GetHeights(iplate,istrip);
1152   step[2] =  GetDistances(iplate,istrip);
1153   Translation(posLocal,step);
1154
1155   // FTOA = FLTA reference frame -> B071/B074/B075 = BTO1/2/3 reference frame
1156   angles[0] = 90.;
1157   angles[1] =  0.;
1158   angles[2] =  0.;
1159   angles[3] =  0.;
1160   angles[4] = 90.;
1161   angles[5] =270.;
1162
1163   InverseRotation(posLocal,angles);
1164
1165   // B071/B074/B075 = BTO1/2/3 reference frame -> ALICE reference frame
1166   step[0] = 0.;
1167   step[1] = 0.;
1168   step[2] = -((fgkRmax+fgkRmin)*0.5);
1169   Translation(posLocal,step);
1170
1171   angles[0] = 90.;
1172   angles[1] = 90.+(isector+0.5)*fgkPhiSec;
1173   angles[2] = 0.;
1174   angles[3] = 0.;
1175   angles[4] = 90.;
1176   angles[5] = (isector+0.5)*fgkPhiSec;
1177
1178   InverseRotation(posLocal,angles);
1179
1180   Float_t xCoor = posLocal[0];
1181
1182   return xCoor;
1183
1184 }
1185 //_____________________________________________________________________________
1186 Float_t AliTOFGeometry::GetY(const Int_t * const det) const
1187 {
1188   //
1189   // Returns Y coordinate (cm)
1190   //
1191
1192   Int_t isector = det[0];
1193   Int_t iplate  = det[1];
1194   Int_t istrip  = det[2];
1195   Int_t ipadz   = det[3];
1196   Int_t ipadx   = det[4];
1197
1198   /*
1199   // Find out distance d on the plane wrt median phi:
1200   Float_t d = (ipadx+0.5-kNpadX*0.5)*fgkXPad;
1201
1202   // The radius r in xy plane:
1203   //Float_t r = (fgkRmin+fgkRmax)*0.5-0.01+GetHeights(iplate,istrip)+
1204   //  (ipadz-0.5)*fgkZPad*TMath::Sin(GetAngles(iplate,istrip)/kRaddeg)-0.25; ???
1205   Float_t r = (fgkRmin+fgkRmax)*0.5-0.01+GetHeights(iplate,istrip)+
1206     (ipadz-0.5)*fgkZPad*TMath::Sin(GetAngles(iplate,istrip)/kRaddeg);
1207
1208   // local azimuthal angle in the sector philoc
1209   Float_t philoc = TMath::ATan(d/r);
1210   //if(philoc<0.) philoc = k2PI + philoc;
1211
1212   // azimuthal angle in the global frame  phi
1213   Float_t phi   = philoc*kRaddeg+(isector+0.5)*fgkPhiSec;
1214
1215   Float_t yCoor = r/TMath::Cos(philoc)*TMath::Sin(phi/kRaddeg);
1216   */
1217
1218   // Pad reference frame -> FSTR reference frame
1219   Float_t posLocal[3] = {0., 0., 0.};
1220   Float_t step[3] = {-(ipadx+0.5)*fgkXPad, 0., -(ipadz+0.5)*fgkZPad};
1221   Translation(posLocal,step);
1222
1223   step[0] = kNpadX*0.5*fgkXPad;
1224   step[1] = 0.;
1225   step[2] = kNpadZ*0.5*fgkZPad;
1226   /*
1227   Float_t posLocal[3] = {(ipadx+0.5)*fgkXPad, 0., (ipadz+0.5)*fgkZPad};
1228   Float_t step[3]= {kNpadX*0.5*fgkXPad, 0., kNpadZ*0.5*fgkZPad};
1229   */
1230   Translation(posLocal,step);
1231
1232   // FSTR reference frame -> FTOA/B/C = FLTA/B/C reference frame
1233
1234   Double_t angles[6] = {0.,0.,0.,0.,0.,0.};
1235   if      (GetAngles(iplate,istrip) >0.) {
1236     angles[0] = 90.;
1237     angles[1] =  0.;
1238     angles[2] = 90.+GetAngles(iplate,istrip);
1239     angles[3] = 90.;
1240     angles[4] = GetAngles(iplate,istrip);
1241     angles[5] = 90.;
1242   }
1243   else if (GetAngles(iplate,istrip)==0.) {
1244     angles[0] = 90.;
1245     angles[1] =  0.;
1246     angles[2] = 90.;
1247     angles[3] = 90.;
1248     angles[4] =  0;
1249     angles[5] =  0.;
1250   }
1251   else if (GetAngles(iplate,istrip) <0.) {
1252     angles[0] = 90.;
1253     angles[1] =  0.;
1254     angles[2] = 90.+GetAngles(iplate,istrip);
1255     angles[3] = 90.;
1256     angles[4] =-GetAngles(iplate,istrip);
1257     angles[5] = 270.;
1258   }
1259
1260   InverseRotation(posLocal,angles);
1261
1262   step[0] = 0.;
1263   step[1] = -GetHeights(iplate,istrip);
1264   step[2] =  GetDistances(iplate,istrip);
1265   Translation(posLocal,step);
1266
1267   // FTOA = FLTA reference frame -> B071/B074/B075 = BTO1/2/3 reference frame
1268   angles[0] = 90.;
1269   angles[1] =  0.;
1270   angles[2] =  0.;
1271   angles[3] =  0.;
1272   angles[4] = 90.;
1273   angles[5] =270.;
1274
1275   InverseRotation(posLocal,angles);
1276
1277   // B071/B074/B075 = BTO1/2/3 reference frame -> ALICE reference frame
1278   step[0] = 0.;
1279   step[1] = 0.;
1280   step[2] = -((fgkRmax+fgkRmin)*0.5);
1281   Translation(posLocal,step);
1282
1283   angles[0] = 90.;
1284   angles[1] = 90.+(isector+0.5)*fgkPhiSec;
1285   angles[2] = 0.;
1286   angles[3] = 0.;
1287   angles[4] = 90.;
1288   angles[5] = (isector+0.5)*fgkPhiSec;
1289
1290   InverseRotation(posLocal,angles);
1291
1292   Float_t yCoor = posLocal[1];
1293
1294   return yCoor;
1295
1296 }
1297
1298 //_____________________________________________________________________________
1299 Float_t AliTOFGeometry::GetZ(const Int_t * const det) const
1300 {
1301   //
1302   // Returns Z coordinate (cm)
1303   //
1304
1305   Int_t isector = det[0];
1306   Int_t iplate  = det[1];
1307   Int_t istrip  = det[2];
1308   Int_t ipadz   = det[3];
1309   Int_t ipadx   = det[4];
1310
1311   /*
1312   Float_t zCoor = GetDistances(iplate,istrip) +
1313     (0.5-ipadz) * fgkZPad * TMath::Cos(GetAngles(iplate,istrip)*kDegrad);
1314   */
1315
1316   // Pad reference frame -> FSTR reference frame
1317   Float_t posLocal[3] = {0., 0., 0.};
1318   Float_t step[3] = {-(ipadx+0.5)*fgkXPad, 0., -(ipadz+0.5)*fgkZPad};
1319   Translation(posLocal,step);
1320
1321   step[0] = kNpadX*0.5*fgkXPad;
1322   step[1] = 0.;
1323   step[2] = kNpadZ*0.5*fgkZPad;
1324   /*
1325   Float_t posLocal[3] = {(ipadx+0.5)*fgkXPad, 0., (ipadz+0.5)*fgkZPad};
1326   Float_t step[3]= {kNpadX*0.5*fgkXPad, 0., kNpadZ*0.5*fgkZPad};
1327   */
1328   Translation(posLocal,step);
1329
1330   // FSTR reference frame -> FTOA/B/C = FLTA/B/C reference frame
1331   Double_t angles[6] = {0.,0.,0.,0.,0.,0.};
1332   if      (GetAngles(iplate,istrip) >0.) {
1333     angles[0] = 90.;
1334     angles[1] =  0.;
1335     angles[2] = 90.+GetAngles(iplate,istrip);
1336     angles[3] = 90.;
1337     angles[4] = GetAngles(iplate,istrip);
1338     angles[5] = 90.;
1339   }
1340   else if (GetAngles(iplate,istrip)==0.) {
1341     angles[0] = 90.;
1342     angles[1] =  0.;
1343     angles[2] = 90.;
1344     angles[3] = 90.;
1345     angles[4] =  0;
1346     angles[5] =  0.;
1347   }
1348   else if (GetAngles(iplate,istrip) <0.) {
1349     angles[0] = 90.;
1350     angles[1] =  0.;
1351     angles[2] = 90.+GetAngles(iplate,istrip);
1352     angles[3] = 90.;
1353     angles[4] =-GetAngles(iplate,istrip);
1354     angles[5] = 270.;
1355   }
1356
1357   InverseRotation(posLocal,angles);
1358
1359   step[0] = 0.;
1360   step[1] = -GetHeights(iplate,istrip);
1361   step[2] =  GetDistances(iplate,istrip);
1362   Translation(posLocal,step);
1363
1364   // FTOA = FLTA reference frame -> B071/B074/B075 = BTO1/2/3 reference frame
1365   angles[0] = 90.;
1366   angles[1] =  0.;
1367   angles[2] =  0.;
1368   angles[3] =  0.;
1369   angles[4] = 90.;
1370   angles[5] =270.;
1371
1372   InverseRotation(posLocal,angles);
1373
1374   // B071/B074/B075 = BTO1/2/3 reference frame -> ALICE reference frame
1375   step[0] = 0.;
1376   step[1] = 0.;
1377   step[2] = -((fgkRmax+fgkRmin)*0.5);
1378   Translation(posLocal,step);
1379
1380   angles[0] = 90.;
1381   angles[1] = 90.+(isector+0.5)*fgkPhiSec;
1382   angles[2] = 0.;
1383   angles[3] = 0.;
1384   angles[4] = 90.;
1385   angles[5] = (isector+0.5)*fgkPhiSec;
1386
1387   InverseRotation(posLocal,angles);
1388
1389   Float_t zCoor = posLocal[2];
1390
1391   return zCoor;
1392
1393 }
1394 //_____________________________________________________________________________
1395
1396 void AliTOFGeometry::DetToSectorRF(Int_t vol[5], Double_t coord[4][3])
1397 {
1398   //
1399   // Returns the local coordinates (x, y, z) in sector reference frame
1400   // for the 4 corners of each sector pad (vol[1], vol[2], vol[3], vol[4])
1401   //
1402
1403   if (!gGeoManager) printf("ERROR: no TGeo\n");
1404
1405   // ALICE -> TOF Sector
1406   Char_t path1[200];
1407   GetVolumePath(vol[0],path1);
1408   gGeoManager->cd(path1);
1409   TGeoHMatrix aliceToSector;
1410   aliceToSector = *gGeoManager->GetCurrentMatrix();
1411
1412   // TOF Sector -> ALICE
1413   //TGeoHMatrix sectorToALICE = aliceToSector.Inverse();
1414
1415   // ALICE -> TOF Pad
1416   Char_t path2[200];
1417   GetVolumePath(vol,path2);
1418   gGeoManager->cd(path2);
1419   TGeoHMatrix aliceToPad;
1420   aliceToPad = *gGeoManager->GetCurrentMatrix();
1421
1422   // TOF Pad -> ALICE
1423   TGeoHMatrix padToALICE = aliceToPad.Inverse();
1424
1425   // TOF Pad -> TOF Sector
1426   TGeoHMatrix padToSector = padToALICE*aliceToSector;
1427
1428   // TOF Sector -> TOF Pad
1429   //TGeoHMatrix sectorToPad = sectorToALICE*aliceToPad;
1430
1431   // coordinates of the pad bottom corner
1432   Double_t **cornerPad = new Double_t*[4];
1433   for (Int_t ii=0; ii<4; ii++) cornerPad[ii] = new Double_t[3];
1434
1435   cornerPad[0][0] = -fgkXPad/2.;
1436   cornerPad[0][1] =  0.;
1437   cornerPad[0][2] = -fgkZPad/2.;
1438
1439   cornerPad[1][0] =  fgkXPad/2.;
1440   cornerPad[1][1] =  0.;
1441   cornerPad[1][2] = -fgkZPad/2.;
1442
1443   cornerPad[2][0] =  fgkXPad/2.;
1444   cornerPad[2][1] =  0.;
1445   cornerPad[2][2] =  fgkZPad/2.;
1446
1447   cornerPad[3][0] = -fgkXPad/2.;
1448   cornerPad[3][1] =  0.;
1449   cornerPad[3][2] =  fgkZPad/2.;
1450
1451   for(Int_t aa=0; aa<4; aa++) for(Int_t bb=0; bb<3; bb++) coord[aa][bb]=0.;
1452
1453   for (Int_t jj=0; jj<4; jj++) padToSector.MasterToLocal(&cornerPad[jj][0], &coord[jj][0]);
1454
1455   delete [] cornerPad;
1456
1457   //sectorToPad.LocalToMaster(cornerPad, coord);
1458
1459 }
1460 //_____________________________________________________________________________
1461 Float_t AliTOFGeometry::GetPadDx(const Float_t * const pos)
1462 {
1463   //
1464   // Returns the x coordinate in the Pad reference frame
1465   //
1466
1467   Float_t xpad = -2.;
1468
1469   Float_t posLocal[3];
1470   for (Int_t ii=0; ii<3; ii++) posLocal[ii] = pos[ii];
1471  
1472   Int_t isector = GetSector(posLocal);
1473   if(isector == -1){
1474     //AliError("Detector Index could not be determined");
1475     return xpad;}
1476   Int_t iplate =  GetPlate(posLocal);
1477   if(iplate == -1){
1478     //AliError("Detector Index could not be determined");
1479     return xpad;} 
1480   Int_t istrip =  GetStrip(posLocal);
1481   if(istrip == -1){  
1482     //AliError("Detector Index could not be determined");
1483     return xpad;}
1484   Int_t ipadz =  GetPadZ(posLocal);
1485   if(ipadz == -1){  
1486     //AliError("Detector Index could not be determined");
1487     return xpad;}
1488   Int_t ipadx =  GetPadX(posLocal);
1489   if(ipadx == -1){
1490     //AliError("Detector Index could not be determined");
1491     return xpad;}
1492
1493   // ALICE reference frame -> B071/B074/B075 = BTO1/2/3 reference frame
1494   Double_t angles[6] = 
1495     {90., 90.+(isector+0.5)*fgkPhiSec,
1496       0.,  0.,
1497      90., (isector+0.5)*fgkPhiSec
1498     };
1499   Rotation(posLocal,angles);
1500
1501   Float_t step[3] = {0., 0., (fgkRmax+fgkRmin)*0.5};
1502   Translation(posLocal,step);
1503
1504   // B071/B074/B075 = BTO1/2/3 reference frame -> FTOA/B/C = FLTA/B/C reference frame
1505   angles[0] = 90.;
1506   angles[1] =  0.;
1507   angles[2] =  0.;
1508   angles[3] =  0.;
1509   angles[4] = 90.;
1510   angles[5] =270.;
1511
1512   Rotation(posLocal,angles);
1513
1514   // FTOA/B/C = FLTA/B/C reference frame -> FSTR reference frame
1515   step[0] = 0.;
1516   step[1] = GetHeights(iplate,istrip);
1517   step[2] = -GetDistances(iplate,istrip);
1518   Translation(posLocal,step);
1519
1520   if      (GetAngles(iplate,istrip) >0.) {
1521     angles[0] = 90.;
1522     angles[1] =  0.;
1523     angles[2] = 90.+GetAngles(iplate,istrip);
1524     angles[3] = 90.;
1525     angles[4] = GetAngles(iplate,istrip);
1526     angles[5] = 90.;
1527   }
1528   else if (GetAngles(iplate,istrip)==0.) {
1529     angles[0] = 90.;
1530     angles[1] =  0.;
1531     angles[2] = 90.;
1532     angles[3] = 90.;
1533     angles[4] =  0;
1534     angles[5] =  0.;
1535   }
1536   else if (GetAngles(iplate,istrip) <0.) {
1537     angles[0] = 90.;
1538     angles[1] =  0.;
1539     angles[2] = 90.+GetAngles(iplate,istrip);
1540     angles[3] = 90.;
1541     angles[4] =-GetAngles(iplate,istrip);
1542     angles[5] = 270.;
1543   }
1544   Rotation(posLocal,angles);
1545
1546   step[0] =-0.5*kNpadX*fgkXPad;
1547   step[1] = 0.;
1548   step[2] =-0.5*kNpadZ*fgkZPad;
1549   Translation(posLocal,step);
1550
1551   step[0] = (ipadx+0.5)*fgkXPad;
1552   step[1] = 0.;
1553   step[2] = (ipadz+0.5)*fgkZPad;
1554   Translation(posLocal,step);
1555   
1556   xpad=posLocal[0];
1557
1558   return xpad;
1559
1560 }
1561 //_____________________________________________________________________________
1562 Float_t AliTOFGeometry::GetPadDy(const Float_t * const pos)
1563 {
1564   //
1565   // Returns the y coordinate in the Pad reference frame
1566   //
1567
1568   Float_t ypad = -2.;
1569
1570   Float_t posLocal[3];
1571   for (Int_t ii=0; ii<3; ii++) posLocal[ii] = pos[ii];
1572  
1573   Int_t isector = GetSector(posLocal);
1574   if(isector == -1){
1575     //AliError("Detector Index could not be determined");
1576     return ypad;}
1577   Int_t iplate =  GetPlate(posLocal);
1578   if(iplate == -1){
1579     //AliError("Detector Index could not be determined");
1580     return ypad;} 
1581   Int_t istrip =  GetStrip(posLocal);
1582   if(istrip == -1){  
1583     //AliError("Detector Index could not be determined");
1584     return ypad;}
1585   Int_t ipadz =  GetPadZ(posLocal);
1586   if(ipadz == -1){  
1587     //AliError("Detector Index could not be determined");
1588     return ypad;}
1589   Int_t ipadx =  GetPadX(posLocal);
1590   if(ipadx == -1){
1591     //AliError("Detector Index could not be determined");
1592     return ypad;}
1593
1594   // ALICE reference frame -> B071/B074/B075 = BTO1/2/3 reference frame
1595   Double_t angles[6] = 
1596     {90., 90.+(isector+0.5)*fgkPhiSec,
1597       0.,  0.,
1598      90., (isector+0.5)*fgkPhiSec
1599     };
1600   Rotation(posLocal,angles);
1601
1602   Float_t step[3] = {0., 0., (fgkRmax+fgkRmin)*0.5};
1603   Translation(posLocal,step);
1604
1605   // B071/B074/B075 = BTO1/2/3 reference frame -> FTOA/B/C = FLTA/B/C reference frame
1606   angles[0] = 90.;
1607   angles[1] =  0.;
1608   angles[2] =  0.;
1609   angles[3] =  0.;
1610   angles[4] = 90.;
1611   angles[5] =270.;
1612
1613   Rotation(posLocal,angles);
1614
1615   // FTOA/B/C = FLTA/B/C reference frame -> FSTR reference frame
1616   step[0] = 0.;
1617   step[1] = GetHeights(iplate,istrip);
1618   step[2] = -GetDistances(iplate,istrip);
1619   Translation(posLocal,step);
1620
1621   if      (GetAngles(iplate,istrip) >0.) {
1622     angles[0] = 90.;
1623     angles[1] =  0.;
1624     angles[2] = 90.+GetAngles(iplate,istrip);
1625     angles[3] = 90.;
1626     angles[4] = GetAngles(iplate,istrip);
1627     angles[5] = 90.;
1628   }
1629   else if (GetAngles(iplate,istrip)==0.) {
1630     angles[0] = 90.;
1631     angles[1] =  0.;
1632     angles[2] = 90.;
1633     angles[3] = 90.;
1634     angles[4] =  0;
1635     angles[5] =  0.;
1636   }
1637   else if (GetAngles(iplate,istrip) <0.) {
1638     angles[0] = 90.;
1639     angles[1] =  0.;
1640     angles[2] = 90.+GetAngles(iplate,istrip);
1641     angles[3] = 90.;
1642     angles[4] =-GetAngles(iplate,istrip);
1643     angles[5] = 270.;
1644   }
1645   Rotation(posLocal,angles);
1646
1647   step[0] =-0.5*kNpadX*fgkXPad;
1648   step[1] = 0.;
1649   step[2] =-0.5*kNpadZ*fgkZPad;
1650   Translation(posLocal,step);
1651   
1652   step[0] = (ipadx+0.5)*fgkXPad;
1653   step[1] = 0.;
1654   step[2] = (ipadz+0.5)*fgkZPad;
1655   Translation(posLocal,step);
1656   
1657   ypad=posLocal[1];
1658   
1659   return ypad;
1660
1661 }
1662 //_____________________________________________________________________________
1663 Float_t AliTOFGeometry::GetPadDz(const Float_t * const pos)
1664 {
1665   //
1666   // Returns the z coordinate in the Pad reference frame
1667   //
1668
1669   Float_t zpad = -2.;
1670
1671   Float_t posLocal[3];
1672   for (Int_t ii=0; ii<3; ii++) posLocal[ii] = pos[ii];
1673  
1674   Int_t isector = GetSector(posLocal);
1675   if(isector == -1){
1676     //AliError("Detector Index could not be determined");
1677     return zpad;}
1678   Int_t iplate =  GetPlate(posLocal);
1679   if(iplate == -1){
1680     //AliError("Detector Index could not be determined");
1681     return zpad;} 
1682   Int_t istrip =  GetStrip(posLocal);
1683   if(istrip == -1){  
1684     //AliError("Detector Index could not be determined");
1685     return zpad;}
1686   Int_t ipadz =  GetPadZ(posLocal);
1687   if(ipadz == -1){  
1688     //AliError("Detector Index could not be determined");
1689     return zpad;}
1690   Int_t ipadx =  GetPadX(posLocal);
1691   if(ipadx == -1){
1692     //AliError("Detector Index could not be determined");
1693     return zpad;}
1694
1695   // ALICE reference frame -> B071/B074/B075 = BTO1/2/3 reference frame
1696   Double_t angles[6] = 
1697     {90., 90.+(isector+0.5)*fgkPhiSec,
1698       0.,  0.,
1699      90., (isector+0.5)*fgkPhiSec
1700     };
1701   Rotation(posLocal,angles);
1702
1703   Float_t step[3] = {0., 0., (fgkRmax+fgkRmin)*0.5};
1704   Translation(posLocal,step);
1705
1706   // B071/B074/B075 = BTO1/2/3 reference frame -> FTOA/B/C = FLTA/B/C reference frame
1707   angles[0] = 90.;
1708   angles[1] =  0.;
1709   angles[2] =  0.;
1710   angles[3] =  0.;
1711   angles[4] = 90.;
1712   angles[5] =270.;
1713
1714   Rotation(posLocal,angles);
1715
1716   // FTOA/B/C = FLTA/B/C reference frame -> FSTR reference frame
1717   step[0] = 0.;
1718   step[1] = GetHeights(iplate,istrip);
1719   step[2] = -GetDistances(iplate,istrip);
1720   Translation(posLocal,step);
1721
1722   if      (GetAngles(iplate,istrip) >0.) {
1723     angles[0] = 90.;
1724     angles[1] =  0.;
1725     angles[2] = 90.+GetAngles(iplate,istrip);
1726     angles[3] = 90.;
1727     angles[4] = GetAngles(iplate,istrip);
1728     angles[5] = 90.;
1729   }
1730   else if (GetAngles(iplate,istrip)==0.) {
1731     angles[0] = 90.;
1732     angles[1] =  0.;
1733     angles[2] = 90.;
1734     angles[3] = 90.;
1735     angles[4] =  0;
1736     angles[5] =  0.;
1737   }
1738   else if (GetAngles(iplate,istrip) <0.) {
1739     angles[0] = 90.;
1740     angles[1] =  0.;
1741     angles[2] = 90.+GetAngles(iplate,istrip);
1742     angles[3] = 90.;
1743     angles[4] =-GetAngles(iplate,istrip);
1744     angles[5] = 270.;
1745   }
1746   Rotation(posLocal,angles);
1747
1748   step[0] =-0.5*kNpadX*fgkXPad;
1749   step[1] = 0.;
1750   step[2] =-0.5*kNpadZ*fgkZPad;
1751   Translation(posLocal,step);
1752   
1753   step[0] = (ipadx+0.5)*fgkXPad;
1754   step[1] = 0.;
1755   step[2] = (ipadz+0.5)*fgkZPad;
1756   Translation(posLocal,step);
1757
1758   zpad=posLocal[2];
1759
1760   return zpad;
1761
1762 }
1763 //_____________________________________________________________________________
1764
1765 void AliTOFGeometry::Translation(Float_t *xyz, Float_t translationVector[3]) const
1766 {
1767   //
1768   // Return the vector xyz translated by translationVector vector
1769   //
1770
1771   Int_t ii=0;
1772
1773   for (ii=0; ii<3; ii++)
1774     xyz[ii] -= translationVector[ii];
1775
1776   return;
1777
1778 }
1779 //_____________________________________________________________________________
1780
1781 void AliTOFGeometry::Rotation(Float_t *xyz, Double_t rotationAngles[6]) const
1782 {
1783   //
1784   // Return the vector xyz rotated according to the rotationAngles angles
1785   //
1786
1787   Int_t ii=0;
1788   /*
1789   TRotMatrix *matrix = new TRotMatrix("matrix","matrix", angles[0], angles[1],
1790                                       angles[2], angles[3],
1791                                       angles[4], angles[5]);
1792   */
1793
1794   for (ii=0; ii<6; ii++) rotationAngles[ii]*=kDegrad;
1795
1796   Float_t xyzDummy[3] = {0., 0., 0.};
1797
1798   for (ii=0; ii<3; ii++) {
1799     xyzDummy[ii] =
1800       xyz[0]*TMath::Sin(rotationAngles[2*ii])*TMath::Cos(rotationAngles[2*ii+1]) +
1801       xyz[1]*TMath::Sin(rotationAngles[2*ii])*TMath::Sin(rotationAngles[2*ii+1]) +
1802       xyz[2]*TMath::Cos(rotationAngles[2*ii]);
1803   }
1804
1805   for (ii=0; ii<3; ii++) xyz[ii]=xyzDummy[ii];
1806
1807   return;
1808
1809 }
1810 //_____________________________________________________________________________
1811 void AliTOFGeometry::InverseRotation(Float_t *xyz, Double_t rotationAngles[6]) const
1812 {
1813   //
1814   // Rotates the vector xyz acordint to the rotationAngles
1815   //
1816
1817   Int_t ii=0;
1818
1819   for (ii=0; ii<6; ii++) rotationAngles[ii]*=kDegrad;
1820
1821   Float_t xyzDummy[3] = {0., 0., 0.};
1822
1823   xyzDummy[0] =
1824     xyz[0]*TMath::Sin(rotationAngles[0])*TMath::Cos(rotationAngles[1]) +
1825     xyz[1]*TMath::Sin(rotationAngles[2])*TMath::Cos(rotationAngles[3]) +
1826     xyz[2]*TMath::Sin(rotationAngles[4])*TMath::Cos(rotationAngles[5]);
1827   
1828   xyzDummy[1] =
1829     xyz[0]*TMath::Sin(rotationAngles[0])*TMath::Sin(rotationAngles[1]) +
1830     xyz[1]*TMath::Sin(rotationAngles[2])*TMath::Sin(rotationAngles[3]) +
1831     xyz[2]*TMath::Sin(rotationAngles[4])*TMath::Sin(rotationAngles[5]);
1832   
1833   xyzDummy[2] =
1834     xyz[0]*TMath::Cos(rotationAngles[0]) +
1835     xyz[1]*TMath::Cos(rotationAngles[2]) +
1836     xyz[2]*TMath::Cos(rotationAngles[4]);
1837   
1838   for (ii=0; ii<3; ii++) xyz[ii]=xyzDummy[ii];
1839
1840   return;
1841
1842 }
1843 //_____________________________________________________________________________
1844
1845 Int_t AliTOFGeometry::GetIndex(const Int_t * const detId)
1846 {
1847   //Retrieve calibration channel index 
1848   Int_t isector = detId[0];
1849   if (isector >= kNSectors){
1850     printf("Wrong sector number in TOF (%d) !\n",isector);
1851     return -1;
1852   }
1853   Int_t iplate = detId[1];
1854   if (iplate >= kNPlates){
1855     printf("Wrong plate number in TOF (%d) !\n",iplate);
1856     return -1;
1857   }
1858   Int_t istrip = detId[2];
1859   Int_t stripOffset = GetStripNumberPerSM(iplate,istrip);
1860   if (stripOffset==-1) {
1861     printf("Wrong strip number per SM in TOF (%d) !\n",stripOffset);
1862     return -1;
1863   }
1864
1865   Int_t ipadz = detId[3];
1866   Int_t ipadx = detId[4];
1867
1868   Int_t idet = ((2*(kNStripC+kNStripB)+kNStripA)*kNpadZ*kNpadX)*isector +
1869                (stripOffset*kNpadZ*kNpadX)+
1870                (kNpadX)*ipadz+
1871                 ipadx;
1872   return idet;
1873 }
1874 //_____________________________________________________________________________
1875
1876 void AliTOFGeometry::GetVolumeIndices(Int_t index, Int_t *detId)
1877 {
1878   //
1879   // Retrieve volume indices from the calibration channel index 
1880   //
1881
1882   detId[0] = index/NpadXStrip()/NStripXSector();
1883
1884   Int_t dummyStripPerModule = 
1885     ( index - ( NStripXSector()*NpadXStrip()*detId[0]) ) / NpadXStrip();
1886   if (dummyStripPerModule<kNStripC) {
1887     detId[1] = 0;
1888     detId[2] = dummyStripPerModule;
1889   }
1890   else if (dummyStripPerModule>=kNStripC && dummyStripPerModule<kNStripC+kNStripB) {
1891     detId[1] = 1;
1892     detId[2] = dummyStripPerModule-kNStripC;
1893   }
1894   else if (dummyStripPerModule>=kNStripC+kNStripB && dummyStripPerModule<kNStripC+kNStripB+kNStripA) {
1895     detId[1] = 2;
1896     detId[2] = dummyStripPerModule-kNStripC-kNStripB;
1897   }
1898   else if (dummyStripPerModule>=kNStripC+kNStripB+kNStripA && dummyStripPerModule<kNStripC+kNStripB+kNStripA+kNStripB) {
1899     detId[1] = 3;
1900     detId[2] = dummyStripPerModule-kNStripC-kNStripB-kNStripA;
1901   }
1902   else if (dummyStripPerModule>=kNStripC+kNStripB+kNStripA+kNStripB && dummyStripPerModule<NStripXSector()) {
1903     detId[1] = 4;
1904     detId[2] = dummyStripPerModule-kNStripC-kNStripB-kNStripA-kNStripB;
1905   }
1906
1907   Int_t padPerStrip = ( index - ( NStripXSector()*NpadXStrip()*detId[0]) ) - dummyStripPerModule*NpadXStrip();
1908
1909   detId[3] = padPerStrip / kNpadX; // padZ
1910   detId[4] = padPerStrip - detId[3]*kNpadX; // padX
1911
1912 }
1913 //_____________________________________________________________________________
1914
1915 Int_t AliTOFGeometry::NStrip(Int_t nPlate)
1916 {
1917   //
1918   // Returns the strips number for the plate number 'nPlate'
1919   //
1920
1921   Int_t nStrips = kNStripC;
1922
1923   switch(nPlate) {
1924   case 2:
1925     nStrips = kNStripA;
1926     break;
1927   case 1:
1928   case 3:
1929     nStrips = kNStripB;
1930     break;
1931   case 0:
1932   case 4:
1933   default:
1934     nStrips = kNStripC;
1935     break;
1936   }
1937
1938   return nStrips;
1939
1940 }
1941 //-------------------------------------------------------------------------
1942
1943 UShort_t AliTOFGeometry::GetAliSensVolIndex(Int_t isector, Int_t iplate, Int_t istrip) const
1944 {
1945   //
1946   // Get the index of the TOF alignable volume in the AliGeomManager order.
1947   //
1948
1949   Int_t index = GetStripNumber(isector, iplate, istrip);
1950
1951   UShort_t volIndex = AliGeomManager::LayerToVolUID(AliGeomManager::kTOF,index);
1952
1953   return volIndex;
1954
1955 }
1956 //-------------------------------------------------------------------------
1957
1958 Int_t AliTOFGeometry::GetStripNumber(Int_t isector, Int_t iplate, Int_t istrip)
1959 {
1960   //
1961   // Get the serial number of the TOF strip number istrip [0,14/18],
1962   //   in the module number iplate [0,4],
1963   //   in the TOF SM number isector [0,17].
1964   // This number will range in [0,1637].
1965   //
1966
1967   Bool_t check = (isector >= kNSectors);
1968
1969   if (check)
1970     printf("E-AliTOFGeometry::GetStripNumber: Wrong sector number in TOF (%d)!\n",isector);
1971
1972   Int_t index = -1;
1973   Int_t stripInSM = GetStripNumberPerSM(iplate, istrip);
1974   if (!check && stripInSM!=-1)
1975     index = (2*(kNStripC+kNStripB)+kNStripA)*isector + stripInSM;
1976
1977   return index;
1978
1979 }
1980 //-------------------------------------------------------------------------
1981
1982 void AliTOFGeometry::GetStripAndModule(Int_t iStripPerSM, Int_t &iplate, Int_t &istrip)
1983 {
1984   //
1985   // Convert the serial number of the TOF strip number iStripPerSM [0,90]
1986   // in module number iplate [0,4] and strip number istrip [0,14/18].
1987   //
1988
1989   if (iStripPerSM<0 || iStripPerSM>=kNStripC+kNStripB+kNStripA+kNStripB+kNStripC) {
1990     iplate = -1;
1991     istrip = -1;
1992   }
1993   else if (iStripPerSM<kNStripC) {
1994     iplate = 0;
1995     istrip = iStripPerSM;
1996   }
1997   else if (iStripPerSM>=kNStripC && iStripPerSM<kNStripC+kNStripB) {
1998     iplate = 1;
1999     istrip = iStripPerSM-kNStripC;
2000   }
2001   else if (iStripPerSM>=kNStripC+kNStripB && iStripPerSM<kNStripC+kNStripB+kNStripA) {
2002     iplate = 2;
2003     istrip = iStripPerSM-kNStripC-kNStripB;
2004   }
2005   else if (iStripPerSM>=kNStripC+kNStripB+kNStripA && iStripPerSM<kNStripC+kNStripB+kNStripA+kNStripB) {
2006     iplate = 3;
2007     istrip = iStripPerSM-kNStripC-kNStripB-kNStripA;
2008   }
2009   else if (iStripPerSM>=kNStripC+kNStripB+kNStripA+kNStripB && iStripPerSM<kNStripC+kNStripB+kNStripA+kNStripB+kNStripC) {
2010     iplate = 4;
2011     istrip = iStripPerSM-kNStripC-kNStripB-kNStripA-kNStripB;
2012   }
2013
2014
2015 }
2016 //-------------------------------------------------------------------------
2017
2018 Int_t AliTOFGeometry::GetStripNumberPerSM(Int_t iplate, Int_t istrip)
2019 {
2020   //
2021   // Get the serial number of the TOF strip number istrip [0,14/18],
2022   //   in the module number iplate [0,4].
2023   // This number will range in [0,90].
2024   //
2025
2026   Int_t index = -1;
2027
2028   Bool_t check = (
2029                   (iplate<0 || iplate>=kNPlates)
2030                   ||
2031                   (
2032                    (iplate==2 && (istrip<0 || istrip>=kNStripA))
2033                    ||
2034                    (iplate!=2 && (istrip<0 || istrip>=kNStripC))
2035                    )
2036                   );
2037
2038   if (iplate<0 || iplate>=kNPlates)
2039     printf("E-AliTOFGeometry::GetStripNumberPerSM: Wrong plate number in TOF (%1d)!\n",iplate);
2040
2041   if (
2042       (iplate==2 && (istrip<0 || istrip>=kNStripA))
2043       ||
2044       (iplate!=2 && (istrip<0 || istrip>=kNStripC))
2045       )
2046     printf("E-AliTOFGeometry::GetStripNumberPerSM: Wrong strip number in TOF "
2047            "(strip=%2d in the plate=%1d)!\n",istrip,iplate);
2048
2049   Int_t stripOffset = 0;
2050   switch (iplate) {
2051   case 0:
2052     stripOffset = 0;
2053     break;
2054   case 1:
2055     stripOffset = kNStripC;
2056     break;
2057   case 2:
2058     stripOffset = kNStripC+kNStripB;
2059     break;
2060   case 3:
2061     stripOffset = kNStripC+kNStripB+kNStripA;
2062     break;
2063   case 4:
2064     stripOffset = kNStripC+kNStripB+kNStripA+kNStripB;
2065     break;
2066   };
2067
2068   if (!check) index = stripOffset + istrip;
2069
2070   return index;
2071
2072 }
2073 //-------------------------------------------------------------------------
2074
2075 void AliTOFGeometry::PadRF2TrackingRF(Float_t *ctrackPos, Float_t *differenceT)
2076 {
2077   //
2078   // To convert the 3D distance ctrackPos, referred to the ALICE RF,
2079   // into the 3D distance differenceT, referred to the tracking RF
2080   // in case ctrakPos belongs to a TOF sensitive volume.
2081   //
2082
2083   for (Int_t ii=0; ii<3; ii++) differenceT[ii] = 999.;
2084
2085   AliDebug(1,Form(" track position in ALICE global Ref. frame -> %f, %f, %f",
2086                   ctrackPos[0],ctrackPos[1],ctrackPos[2]));
2087
2088   Int_t detId[5] = {-1,-1,-1,-1,-1};
2089
2090   detId[0] = GetSector(ctrackPos);
2091   if (detId[0]==-1) {
2092     AliWarning(Form("This point does not belong to any TOF sector"));
2093     return;
2094   }
2095
2096   detId[1] = GetPlate(ctrackPos);
2097   if (detId[1]==-1) {
2098     AliWarning(Form("This point does not belong to any TOF module"));
2099     return;
2100   }
2101
2102   detId[2] = GetStrip(ctrackPos);
2103   if (detId[2]==-1) {
2104     AliWarning(Form("This point does not belong to any TOF strip"));
2105     return;
2106   }
2107
2108   detId[3] = GetPadZ(ctrackPos);
2109   if (detId[3]==-1) {
2110     AliWarning(Form("This point does not belong to any TOF pad-row"));
2111     return;
2112   }
2113
2114   detId[4] = GetPadX(ctrackPos);
2115   if (detId[4]==-1) {
2116     AliWarning(Form("This point does not belong to any TOF pad"));
2117     return;
2118   }
2119
2120
2121   UShort_t alignableStripIndex =
2122     GetAliSensVolIndex(detId[0],detId[1],detId[2]);
2123   AliDebug(1,Form(" sector = %2d, plate = %1d, strip = %2d (padZ = %1d, padX = %2d) "
2124                   "---> stripIndex = %4d",
2125                   detId[0], detId[1], detId[2], detId[3], detId[4], alignableStripIndex));
2126
2127   // pad centre coordinates in the strip ref. frame
2128   Double_t padCentreL[3] = {(detId[4]-AliTOFGeometry::NpadX()/2)*AliTOFGeometry::XPad()
2129                             +AliTOFGeometry::XPad()/2.,
2130                             0.,
2131                             (detId[3]-AliTOFGeometry::NpadZ()/2)*AliTOFGeometry::XPad()
2132                             +AliTOFGeometry::XPad()/2.};
2133   // pad centre coordinates in the strip tracking frame
2134   Double_t padCentreT[3] = {0., 0., 0.};
2135   TGeoHMatrix l2t = *AliGeomManager::GetTracking2LocalMatrix(alignableStripIndex);
2136   l2t.MasterToLocal(padCentreL,padCentreT);
2137
2138
2139   Char_t path[200];
2140   // pad centre coordinates in its ref. frame
2141   Double_t padCentreL2[3] = {0., 0., 0.};
2142   // pad centre coordinates in the ALICE global ref. frame
2143   Double_t padCentreG[3] = {0., 0., 0.};
2144   GetVolumePath(detId,path);
2145   gGeoManager->cd(path);
2146   TGeoHMatrix g2l = *gGeoManager->GetCurrentMatrix();
2147   TGeoHMatrix l2g = g2l.Inverse();
2148   l2g.MasterToLocal(padCentreL2,padCentreG);
2149
2150
2151   Char_t path2[200];
2152   // strip centre coordinates in its ref. frame
2153   Double_t stripCentreL[3] = {0., 0., 0.};
2154   // strip centre coordinates in the ALICE global ref. frame
2155   Double_t stripCentreG[3] = {0., 0., 0.};
2156   GetVolumePath(detId[0],detId[1],detId[2],path2);
2157   gGeoManager->cd(path2);
2158   TGeoHMatrix g2lb = *gGeoManager->GetCurrentMatrix();
2159   TGeoHMatrix l2gb = g2lb.Inverse();
2160   l2gb.MasterToLocal(stripCentreL,stripCentreG);
2161
2162   TGeoHMatrix g2t = 0;
2163   AliGeomManager::GetTrackingMatrix(alignableStripIndex, g2t);
2164
2165   // track position in the ALICE global ref. frame
2166   Double_t posG[3];
2167   for (Int_t ii=0; ii<3; ii++) posG[ii] = (Double_t)ctrackPos[ii];
2168
2169   // strip centre coordinates in the tracking ref. frame
2170   Double_t stripCentreT[3] = {0., 0., 0.};
2171   // track position in the tracking ref. frame
2172   Double_t posT[3] = {0., 0., 0.};
2173   g2t.MasterToLocal(posG,posT);
2174   g2t.MasterToLocal(stripCentreG,stripCentreT);
2175
2176   for (Int_t ii=0; ii<3; ii++)
2177     AliDebug(1,Form(" track position in ALICE global and tracking RFs -> posG[%d] = %f --- posT[%d] = %f",
2178                     ii, posG[ii], ii, posT[ii]));
2179   for (Int_t ii=0; ii<3; ii++)
2180     AliDebug(1,Form(" pad centre coordinates in its, the ALICE global and tracking RFs -> "
2181                     "padCentreL[%d] = %f --- padCentreG[%d] = %f --- padCentreT[%d] = %f",
2182                     ii, padCentreL[ii],
2183                     ii, padCentreG[ii],
2184                     ii, padCentreT[ii]));
2185   for (Int_t ii=0; ii<3; ii++)
2186     AliDebug(1,Form(" strip centre coordinates in its, the ALICE global and tracking RFs -> "
2187                     "stripCentreL[%d] = %f --- stripCentreG[%d] = %f --- stripCentreT[%d] = %f",
2188                     ii, stripCentreL[ii],
2189                     ii, stripCentreG[ii],
2190                     ii, stripCentreT[ii]));
2191   for (Int_t ii=0; ii<3; ii++)
2192     AliDebug(1,Form(" difference between the track position and the pad centre in the tracking RF "
2193                     "-> posT[%d]-padCentreT[%d] = %f",
2194                     ii,ii,
2195                     posT[ii]-padCentreT[ii]));
2196
2197   for (Int_t ii=0; ii<3; ii++) differenceT[ii] = (Float_t)(posT[ii]-padCentreT[ii]);
2198
2199 }
2200 //-------------------------------------------------------------------------
2201
2202 Int_t AliTOFGeometry::GetTOFsupermodule(const Int_t index)
2203 {
2204   // Return the TOF supermodule where TOF channel index is located
2205
2206   if (index<0 || index>=NPadXSector()*NSectors()) return -1;
2207   else return index/NpadXStrip()/NStripXSector();
2208
2209 }