New class for ITS coordiante transformations used by AliITSgeom nearly
[u/mrichter/AliRoot.git] / ITS / AliITSgeomMatrix.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.1.2.1  2000/06/04 16:32:31  Nilsen
19 A new class to hold the matrix information needed by AliITSgeom.
20
21 */
22 #include <iostream.h>
23 #include <TMath.h>
24 #include <TBuffer.h>
25
26 #include "AliITSgeomMatrix.h"
27
28 ClassImp(AliITSgeomMatrix)
29 //----------------------------------------------------------------------
30 AliITSgeomMatrix::AliITSgeomMatrix(){
31 ////////////////////////////////////////////////////////////////////////
32 // The Default constructor for the AliITSgeomMatrix class. By Default
33 // the angles of rotations are set to zero, meaning that the rotation
34 // matrix is the unit matrix. The translation vector is also set to zero
35 // as are the module id number. The detector type is set to -1 (an undefined
36 // value). The full rotation matrix is kept so that the evaluation 
37 // of a coordinate transformation can be done quickly and with a minimum
38 // of CPU overhead. The basic coordinate systems are the ALICE global
39 // coordinate system and the detector local coordinate system. In general
40 // this structure is not limited to just those two coordinate systems.
41 //Begin_Html
42 /*
43 <img src="picts/ITS/AliISgeomMatrix_L1.gif">
44 */
45 //End_Html
46 ////////////////////////////////////////////////////////////////////////
47     Int_t i,j;
48
49     fDetectorIndex = -1; // a value never defined.
50     for(i=0;i<3;i++){
51         fid[i] = 0;
52         frot[i] = ftran[i] = 0.0;
53         for(j=0;j<3;j++) fm[i][j] = 0.0;
54     }// end for i
55     fm[0][0] = fm[1][1] = fm[2][2] = 1.0;
56 }
57 //----------------------------------------------------------------------
58 AliITSgeomMatrix::AliITSgeomMatrix(const AliITSgeomMatrix &sourse){
59 ////////////////////////////////////////////////////////////////////////
60 // The standard copy constructor. This make a full / proper copy of
61 // this class.
62 ////////////////////////////////////////////////////////////////////////
63         Int_t i,j;
64
65         this->fDetectorIndex = sourse.fDetectorIndex;
66         for(i=0;i<3;i++){
67                 this->fid[i]     = sourse.fid[i];
68                 this->frot[i]    = sourse.frot[i];
69                 this->ftran[i]   = sourse.ftran[i];
70                 for(j=0;j<3;j++) this->fm[i][j] = sourse.fm[i][j];
71         }// end for i
72 }
73 //----------------------------------------------------------------------
74 void AliITSgeomMatrix::operator=(const AliITSgeomMatrix &sourse){
75 ////////////////////////////////////////////////////////////////////////
76 // The standard = operator. This make a full / proper copy of
77 // this class.
78 ////////////////////////////////////////////////////////////////////////
79         Int_t i,j;
80
81         this->fDetectorIndex = sourse.fDetectorIndex;
82         for(i=0;i<3;i++){
83                 this->fid[i]     = sourse.fid[i];
84                 this->frot[i]    = sourse.frot[i];
85                 this->ftran[i]   = sourse.ftran[i];
86                 for(j=0;j<3;j++) this->fm[i][j] = sourse.fm[i][j];
87         }// end for i
88 }
89 //----------------------------------------------------------------------
90 AliITSgeomMatrix::AliITSgeomMatrix(const Int_t idt,const Int_t id[3],
91                    const Double_t rot[3],const Double_t tran[3]){
92 ////////////////////////////////////////////////////////////////////////
93 // This is a constructor for the AliITSgeomMatrix class. The matrix is
94 // defined by 3 standard rotation angles [radians], and the translation
95 // vector tran [cm]. In addition the layer, ladder, and detector number
96 // for this particular module and the type of module must be given.
97 // The full rotation matrix is kept so that the evaluation 
98 // of a coordinate transformation can be done quickly and with a minimum
99 // of CPU overhead. The basic coordinate systems are the ALICE global
100 // coordinate system and the detector local coordinate system. In general
101 // this structure is not limited to just those two coordinate systems.
102 //Begin_Html
103 /*
104 <img src="picts/ITS/AliISgeomMatrix_L1.gif">
105 */
106 //End_Html
107 ////////////////////////////////////////////////////////////////////////
108         Int_t i;
109
110         fDetectorIndex = idt; // a value never defined.
111         for(i=0;i<3;i++){
112                 fid[i]   = id[i];
113                 frot[i]  = rot[i];
114                 ftran[i] = tran[i];
115         }// end for i
116         this->MatrixFromAngle();
117 }
118 //----------------------------------------------------------------------
119 AliITSgeomMatrix::AliITSgeomMatrix(const Int_t idt, const Int_t id[3],
120                                    const Double_t matrix[3][3],
121                                    const Double_t tran[3]){
122 ////////////////////////////////////////////////////////////////////////
123 // This is a constructor for the AliITSgeomMatrix class. The rotation matrix
124 // is given as one of the inputs, and the translation vector tran [cm]. In 
125 // addition the layer, ladder, and detector number for this particular
126 // module and the type of module must be given. The full rotation matrix
127 // is kept so that the evaluation of a coordinate transformation can be
128 // done quickly and with a minimum of CPU overhead. The basic coordinate
129 // systems are the ALICE global coordinate system and the detector local
130 // coordinate system. In general this structure is not limited to just
131 // those two coordinate systems.
132 //Begin_Html
133 /*
134 <img src="picts/ITS/AliISgeomMatrix_L1.gif">
135 */
136 //End_Html
137 ////////////////////////////////////////////////////////////////////////
138         Int_t i,j;
139
140         fDetectorIndex = idt; // a value never defined.
141         for(i=0;i<3;i++){
142                 fid[i]   = id[i];
143                 ftran[i] = tran[i];
144                 for(j=0;j<3;j++) fm[i][j] = matrix[i][j];
145         }// end for i
146         this->AngleFromMatrix();
147 }
148 //----------------------------------------------------------------------
149 void AliITSgeomMatrix::SixAnglesFromMatrix(Double_t *ang){
150 ////////////////////////////////////////////////////////////////////////
151 // This function returns the 6 GEANT 3.21 rotation angles [degrees] in
152 // the array ang which must be at least [6] long.
153 ////////////////////////////////////////////////////////////////////////
154     Double_t si,c=180./TMath::Pi();
155
156     ang[1] = TMath::ATan2(fm[0][1],fm[0][0]);
157     if(TMath::Cos(ang[1])!=0.0) si = fm[0][0]/TMath::Cos(ang[1]);
158     else si = fm[0][1]/TMath::Sin(ang[1]);
159     ang[0] = TMath::ATan2(si,fm[0][2]);
160
161     ang[3] = TMath::ATan2(fm[1][1],fm[1][0]);
162     if(TMath::Cos(ang[3])!=0.0) si = fm[1][0]/TMath::Cos(ang[3]);
163     else si = fm[1][1]/TMath::Sin(ang[3]);
164     ang[4] = TMath::ATan2(si,fm[1][2]);
165
166     ang[6] = TMath::ATan2(fm[2][1],fm[2][0]);
167     if(TMath::Cos(ang[6])!=0.0) si = fm[2][0]/TMath::Cos(ang[6]);
168     else si = fm[2][1]/TMath::Sin(ang[6]);
169     ang[5] = TMath::ATan2(si,fm[2][2]);
170
171     for(Int_t i=0;i<6;i++) {ang[i] *= c; if(ang[i]<0.0) ang[i] += 360.;}
172 }
173 //----------------------------------------------------------------------
174 void AliITSgeomMatrix::MatrixFromSixAngles(const Double_t *ang){
175 ////////////////////////////////////////////////////////////////////////
176 // Given the 6 GEANT 3.21 rotation angles [degree], this will compute and
177 // set the rotations matrix and 3 standard rotation angles [radians].
178 // These angles and rotation matrix are overwrite the existing values in
179 // this class.
180 ////////////////////////////////////////////////////////////////////////
181     Int_t    i,j;
182     Double_t si,lr[9],c=TMath::Pi()/180.;
183
184     si    = TMath::Sin(c*ang[0]);
185     if(ang[0]== 90.0)                 si = +1.0;
186     if(ang[0]==270.0)                 si = -1.0;
187     if(ang[0]==  0.0||ang[0]==180.) si =  0.0;
188     lr[0] = si * TMath::Cos(c*ang[1]);
189     lr[1] = si * TMath::Sin(c*ang[1]);
190     lr[2] = TMath::Cos(c*ang[0]);
191     if(ang[0]== 90.0||ang[0]==270.) lr[2] =  0.0;
192     if(ang[0]== 0.0)                  lr[2] = +1.0;
193     if(ang[0]==180.0)                 lr[2] = -1.0;
194 //
195     si    =  TMath::Sin(c*ang[2]);
196     if(ang[2]== 90.0)                 si = +1.0; 
197     if(ang[2]==270.0)                 si = -1.0;
198     if(ang[2]==  0.0||ang[2]==180.) si =  0.0;
199     lr[3] = si * TMath::Cos(c*ang[3]);
200     lr[4] = si * TMath::Sin(c*ang[3]);
201     lr[5] = TMath::Cos(c*ang[2]);
202     if(ang[2]== 90.0||ang[2]==270.) lr[5] =  0.0;
203     if(ang[2]==  0.0)                 lr[5] = +1.0;
204     if(ang[2]==180.0)                 lr[5] = -1.0;
205 //
206     si    = TMath::Sin(c*ang[4]);
207     if(ang[4]== 90.0)                 si = +1.0;
208     if(ang[4]==270.0)                 si = -1.0;
209     if(ang[4]==  0.0||ang[4]==180.) si =  0.0;
210     lr[6] = si * TMath::Cos(c*ang[5]);
211     lr[7] = si * TMath::Sin(c*ang[5]);
212     lr[8] = TMath::Cos(c*ang[4]);
213     if(ang[4]== 90.0||ang[4]==270.0) lr[8] =  0.0;
214     if(ang[4]==  0.0)                  lr[8] = +1.0;
215     if(ang[4]==180.0)                  lr[8] = -1.0;
216     // Normalize these elements and fill matrix fm.
217     for(i=0;i<3;i++){// reuse si.
218         si = 0.0;
219         for(j=0;j<3;j++) si += lr[3*i+j]*lr[3*i+j];
220         si = TMath::Sqrt(1./si);
221         for(j=0;j<3;j++) fm[i][j] = si*lr[3*i+j];
222     } // end for i
223     this->AngleFromMatrix();
224 }
225 //----------------------------------------------------------------------
226 AliITSgeomMatrix::AliITSgeomMatrix(const Double_t rotd[6]/*degrees*/,
227                                    const Int_t idt,const Int_t id[3],
228                                    const Double_t tran[3]){
229 ////////////////////////////////////////////////////////////////////////
230 // This is a constructor for the AliITSgeomMatrix class. The matrix is
231 // defined by the 6 GEANT 3.21 rotation angles [degrees], and the translation
232 // vector tran [cm]. In addition the layer, ladder, and detector number
233 // for this particular module and the type of module must be given.
234 // The full rotation matrix is kept so that the evaluation 
235 // of a coordinate transformation can be done quickly and with a minimum
236 // of CPU overhead. The basic coordinate systems are the ALICE global
237 // coordinate system and the detector local coordinate system. In general
238 // this structure is not limited to just those two coordinate systems.
239 //Begin_Html
240 /*
241 <img src="picts/ITS/AliISgeomMatrix_L1.gif">
242 */
243 //End_Html
244 ////////////////////////////////////////////////////////////////////////
245     Int_t i;
246
247     fDetectorIndex = idt; // a value never defined.
248     for(i=0;i<3;i++){
249         fid[i]   = id[i];
250         ftran[i] = tran[i];
251     }// end for i
252     this->MatrixFromSixAngles(rotd);
253 }
254 //----------------------------------------------------------------------
255 void AliITSgeomMatrix::AngleFromMatrix(){
256 ////////////////////////////////////////////////////////////////////////
257 // Computes the angles from the rotation matrix up to a phase of 180 degrees.
258 ////////////////////////////////////////////////////////////////////////
259     Double_t rx,ry,rz;
260     // get angles from matrix up to a phase of 180 degrees.
261
262     rx = TMath::ATan2(fm[2][1],fm[2][2]);if(rx<0.0) rx += 2.0*TMath::Pi();
263     ry = TMath::ASin(fm[0][2]);          if(ry<0.0) ry += 2.0*TMath::Pi();
264     rz = TMath::ATan2(fm[1][1],fm[0][0]);if(rz<0.0) rz += 2.0*TMath::Pi();
265     frot[0] = rx;
266     frot[1] = ry;
267     frot[2] = rz;
268     return;
269 }
270 //----------------------------------------------------------------------
271 void AliITSgeomMatrix::MatrixFromAngle(){
272 ////////////////////////////////////////////////////////////////////////
273 // Computes the Rotation matrix from the angles [radians] kept in this
274 // class.
275 ////////////////////////////////////////////////////////////////////////
276    Double_t sx,sy,sz,cx,cy,cz;
277
278    sx = TMath::Sin(frot[0]); cx = TMath::Cos(frot[0]);
279    sy = TMath::Sin(frot[1]); cy = TMath::Cos(frot[1]);
280    sz = TMath::Sin(frot[2]); cz = TMath::Cos(frot[2]);
281    fm[0][0] =  cz*cy;             // fr[0]
282    fm[0][1] = -cz*sy*sx - sz*cx;  // fr[1]
283    fm[0][2] = -cz*sy*cx + sz*sx;  // fr[2]
284    fm[1][0] =  sz*cy;             // fr[3]
285    fm[1][1] = -sz*sy*sx + cz*cx;  // fr[4]
286    fm[1][2] = -sz*sy*cx - cz*sx;  // fr[5]
287    fm[2][0] =  sy;                // fr[6]
288    fm[2][1] =  cy*sx;             // fr[7]
289    fm[2][2] =  cy*cx;             // fr[8]
290
291 }
292 //----------------------------------------------------------------------
293 void AliITSgeomMatrix::GtoLPosition(const Double_t g0[3],Double_t l[3]){
294 ////////////////////////////////////////////////////////////////////////
295 // Returns the local coordinates given the global coordinates [cm].
296 ////////////////////////////////////////////////////////////////////////
297         Int_t    i,j;
298         Double_t g[3];
299
300         for(i=0;i<3;i++) g[i] = g0[i] - ftran[i];
301         for(i=0;i<3;i++){
302                 l[i] = 0.0;
303                 for(j=0;j<3;j++) l[i] += fm[i][j]*g[j];
304                 // g = R l + translation
305         } // end for i
306         return;
307 }
308 //----------------------------------------------------------------------
309 void AliITSgeomMatrix::LtoGPosition(const Double_t l[3],Double_t g[3]){
310 ////////////////////////////////////////////////////////////////////////
311 // Returns the global coordinates given the local coordinates [cm].
312 ////////////////////////////////////////////////////////////////////////
313         Int_t    i,j;
314
315         for(i=0;i<3;i++){
316                 g[i] = 0.0;
317                 for(j=0;j<3;j++) g[i] += fm[j][i]*l[j];
318                 g[i] += ftran[i];
319                 // g = R^t l + translation
320         } // end for i
321         return;
322 }
323 //----------------------------------------------------------------------
324 void AliITSgeomMatrix::GtoLMomentum(const Double_t g[3],Double_t l[3]){
325 ////////////////////////////////////////////////////////////////////////
326 // Returns the local coordinates of the momentum given the global
327 // coordinates of the momentum. It transforms just like GtoLPosition
328 // except that the translation vector is zero.
329 ////////////////////////////////////////////////////////////////////////
330         Int_t    i,j;
331
332         for(i=0;i<3;i++){
333                 l[i] = 0.0;
334                 for(j=0;j<3;j++) l[i] += fm[i][j]*g[j];
335                 // g = R l
336         } // end for i
337         return;
338 }
339 //----------------------------------------------------------------------
340 void AliITSgeomMatrix::LtoGMomentum(const Double_t l[3],Double_t g[3]){
341 ////////////////////////////////////////////////////////////////////////
342 // Returns the Global coordinates of the momentum given the local
343 // coordinates of the momentum. It transforms just like LtoGPosition
344 // except that the translation vector is zero.
345 ////////////////////////////////////////////////////////////////////////
346         Int_t    i,j;
347
348         for(i=0;i<3;i++){
349                 g[i] = 0.0;
350                 for(j=0;j<3;j++) g[i] += fm[j][i]*l[j];
351                 // g = R^t l
352         } // end for i
353         return;
354 }
355 //----------------------------------------------------------------------
356 void AliITSgeomMatrix::GtoLPositionError(const Double_t g[3][3],
357                                                Double_t l[3][3]){
358 ////////////////////////////////////////////////////////////////////////
359 // Given an Uncertainty matrix in Global coordinates it is rotated so that 
360 // its representation in local coordinates can be returned. There is no
361 // effect due to the translation vector or its uncertainty.
362 ////////////////////////////////////////////////////////////////////////
363         Int_t    i,j,k,m;
364
365         for(i=0;i<3;i++)for(j=0;j<3;j++)for(k=0;k<3;k++)for(m=0;m<3;m++)
366                 l[i][m] = fm[j][i]*g[j][k]*fm[k][m];
367                 // g = R^t l R
368         return;
369 }
370 //----------------------------------------------------------------------
371 void AliITSgeomMatrix::LtoGPositionError(const Double_t l[3][3],
372                                                Double_t g[3][3]){
373 ////////////////////////////////////////////////////////////////////////
374 // Given an Uncertainty matrix in Local coordinates it is rotated so that 
375 // its representation in global coordinates can be returned. There is no
376 // effect due to the translation vector or its uncertainty.
377 ////////////////////////////////////////////////////////////////////////
378         Int_t    i,j,k,m;
379
380         for(i=0;i<3;i++)for(j=0;j<3;j++)for(k=0;k<3;k++)for(m=0;m<3;m++)
381                 g[i][m] = fm[i][j]*l[j][k]*fm[m][k];
382                 // g = R l R^t
383         return;
384 }
385 //----------------------------------------------------------------------
386 void AliITSgeomMatrix::GtoLPositionTracking(const Double_t g0[3],
387                                             Double_t l[3]){
388 ////////////////////////////////////////////////////////////////////////
389 // A slightly different coordinate system is used when tracking.
390 // This coordinate system is only relevant when the geometry represents
391 // the cylindrical ALICE ITS geometry. For tracking the Z axis is left
392 // alone but X -> -Y and Y -> X such that X always points out of the
393 // ITS Cylinder for every layer including layer 1 (where the detector 
394 // are mounted upside down).
395 //Begin_Html
396 /*
397 <img src="picts/ITS/AliITSgeomMatrix_T1.gif">
398  */
399 //End_Html
400 ////////////////////////////////////////////////////////////////////////
401     Double_t l0[3];
402
403     this->GtoLPosition(g0,l0);
404     if(fid[0]==1){ // for layer 1 the detector are flipped upside down
405                    // with respect to the others.
406         l[0] = +l0[1];
407         l[1] = -l0[0];
408         l[2] = +l0[2];
409     }else{
410         l[0] = -l0[1];
411         l[1] = +l0[0];
412         l[2] = +l0[2];
413     } // end if
414     return;
415 }
416 //----------------------------------------------------------------------
417 void AliITSgeomMatrix::LtoGPositionTracking(const Double_t l[3],
418                                             Double_t g[3]){
419 ////////////////////////////////////////////////////////////////////////
420 // A slightly different coordinate system is used when tracking.
421 // This coordinate system is only relevant when the geometry represents
422 // the cylindrical ALICE ITS geometry. For tracking the Z axis is left
423 // alone but X -> -Y and Y -> X such that X always points out of the
424 // ITS Cylinder for every layer including layer 1 (where the detector 
425 // are mounted upside down).
426 //Begin_Html
427 /*
428 <img src="picts/ITS/AliITSgeomMatrix_T1.gif">
429  */
430 //End_Html
431 ////////////////////////////////////////////////////////////////////////
432     Double_t l0[3];
433
434     if(fid[0]==1){ // for layer 1 the detector are flipped upside down
435                    // with respect to the others.
436         l0[0] = -l[1];
437         l0[1] = +l[0];
438         l0[2] = +l[2];
439     }else{
440         l0[0] = +l[1];
441         l0[1] = -l[0];
442         l0[2] = +l[2];
443     } // end if
444     this->LtoGPosition(l0,g);
445     return;
446 }
447 //----------------------------------------------------------------------
448 void AliITSgeomMatrix::GtoLMomentumTracking(const Double_t g[3],
449                                             Double_t l[3]){
450 ////////////////////////////////////////////////////////////////////////
451 // A slightly different coordinate system is used when tracking.
452 // This coordinate system is only relevant when the geometry represents
453 // the cylindrical ALICE ITS geometry. For tracking the Z axis is left
454 // alone but X -> -Y and Y -> X such that X always points out of the
455 // ITS Cylinder for every layer including layer 1 (where the detector 
456 // are mounted upside down).
457 //Begin_Html
458 /*
459 <img src="picts/ITS/AliITSgeomMatrix_T1.gif">
460  */
461 //End_Html
462 ////////////////////////////////////////////////////////////////////////
463     Double_t l0[3];
464
465     this->GtoLMomentum(g,l0);
466     if(fid[0]==1){ // for layer 1 the detector are flipped upside down
467                    // with respect to the others.
468         l[0] = +l0[1];
469         l[1] = -l0[0];
470         l[2] = +l0[2];
471     }else{
472         l[0] = -l0[1];
473         l[1] = +l0[0];
474         l[2] = +l0[2];
475     } // end if
476     return;
477         return;
478 }
479 //----------------------------------------------------------------------
480 void AliITSgeomMatrix::LtoGMomentumTracking(const Double_t l[3],
481                                             Double_t g[3]){
482 ////////////////////////////////////////////////////////////////////////
483 // A slightly different coordinate system is used when tracking.
484 // This coordinate system is only relevant when the geometry represents
485 // the cylindrical ALICE ITS geometry. For tracking the Z axis is left
486 // alone but X -> -Y and Y -> X such that X always points out of the
487 // ITS Cylinder for every layer including layer 1 (where the detector 
488 // are mounted upside down).
489 //Begin_Html
490 /*
491 <img src="picts/ITS/AliITSgeomMatrix_T1.gif">
492  */
493 //End_Html
494 ////////////////////////////////////////////////////////////////////////
495     Double_t l0[3];
496
497     if(fid[0]==1){ // for layer 1 the detector are flipped upside down
498                    // with respect to the others.
499         l0[0] = -l[1];
500         l0[1] = +l[0];
501         l0[2] = +l[2];
502     }else{
503         l0[0] = +l[1];
504         l0[1] = -l[0];
505         l0[2] = +l[2];
506     } // end if
507     this->LtoGMomentum(l0,g);
508         return;
509 }
510 //----------------------------------------------------------------------
511 void AliITSgeomMatrix::GtoLPositionErrorTracking(const Double_t g[3][3],
512                                                  Double_t l[3][3]){
513 ////////////////////////////////////////////////////////////////////////
514 // A slightly different coordinate system is used when tracking.
515 // This coordinate system is only relevant when the geometry represents
516 // the cylindrical ALICE ITS geometry. For tracking the Z axis is left
517 // alone but X -> -Y and Y -> X such that X always points out of the
518 // ITS Cylinder for every layer including layer 1 (where the detector 
519 // are mounted upside down).
520 //Begin_Html
521 /*
522 <img src="picts/ITS/AliITSgeomMatrix_T1.gif">
523  */
524 //End_Html
525 ////////////////////////////////////////////////////////////////////////
526         Int_t    i,j,k,m;
527         Double_t Rt[3][3];
528         Double_t A0[3][3] = {{0.,+1.,0.},{-1.,0.,0.},{0.,0.,+1.}};
529         Double_t A1[3][3] = {{0.,-1.,0.},{+1.,0.,0.},{0.,0.,+1.}};
530
531         if(fid[0]==1) for(i=0;i<3;i++)for(j=0;j<3;j++)for(k=0;k<3;k++)
532             Rt[i][k] = A0[i][j]*fm[j][k];
533         else for(i=0;i<3;i++)for(j=0;j<3;j++)for(k=0;k<3;k++)
534             Rt[i][k] = A1[i][j]*fm[j][k];
535         for(i=0;i<3;i++)for(j=0;j<3;j++)for(k=0;k<3;k++)for(m=0;m<3;m++)
536                 l[i][m] = Rt[j][i]*g[j][k]*Rt[k][m];
537                 // g = R^t l R
538         return;
539 }
540 //----------------------------------------------------------------------
541 void AliITSgeomMatrix::LtoGPositionErrorTracking(const Double_t l[3][3],
542                                                  Double_t g[3][3]){
543 ////////////////////////////////////////////////////////////////////////
544 // A slightly different coordinate system is used when tracking.
545 // This coordinate system is only relevant when the geometry represents
546 // the cylindrical ALICE ITS geometry. For tracking the Z axis is left
547 // alone but X -> -Y and Y -> X such that X always points out of the
548 // ITS Cylinder for every layer including layer 1 (where the detector 
549 // are mounted upside down).
550 //Begin_Html
551 /*
552 <img src="picts/ITS/AliITSgeomMatrix_T1.gif">
553  */
554 //End_Html
555 ////////////////////////////////////////////////////////////////////////
556         Int_t    i,j,k,m;
557         Double_t Rt[3][3];
558         Double_t A0[3][3] = {{0.,+1.,0.},{-1.,0.,0.},{0.,0.,+1.}};
559         Double_t A1[3][3] = {{0.,-1.,0.},{+1.,0.,0.},{0.,0.,+1.}};
560
561         if(fid[0]==1) for(i=0;i<3;i++)for(j=0;j<3;j++)for(k=0;k<3;k++)
562             Rt[i][k] = A0[i][j]*fm[j][k];
563         else for(i=0;i<3;i++)for(j=0;j<3;j++)for(k=0;k<3;k++)
564             Rt[i][k] = A1[i][j]*fm[j][k];
565         for(i=0;i<3;i++)for(j=0;j<3;j++)for(k=0;k<3;k++)for(m=0;m<3;m++)
566                 g[i][m] = Rt[i][j]*l[j][k]*Rt[m][k];
567                 // g = R l R^t
568         return;
569 }
570 //----------------------------------------------------------------------
571 void AliITSgeomMatrix::PrintTitles(ostream *os){
572 ////////////////////////////////////////////////////////////////////////
573 // Standard output format for this class but it includes variable
574 // names and formatting that makes it easer to read.
575 ////////////////////////////////////////////////////////////////////////
576     Int_t i,j;
577
578     *os << "fDetectorIndex=" << fDetectorIndex << " fid[3]={";
579     for(i=0;i<3;i++) *os << fid[i]   << " ";
580     *os << "} frot[3]={";
581     for(i=0;i<3;i++) *os << frot[i]  << " ";
582     *os << "} ftran[3]={";
583     for(i=0;i<3;i++) *os << ftran[i] << " ";
584     *os << "} fm[3][3]={";
585     for(i=0;i<3;i++){for(j=0;j<3;j++){  *os << fm[i][j] << " ";} *os <<"}{";}
586     *os << "}" << endl;
587     return;
588 }
589 //----------------------------------------------------------------------
590 void AliITSgeomMatrix::print(ostream *os){
591 ////////////////////////////////////////////////////////////////////////
592 // Standard output format for this class.
593 ////////////////////////////////////////////////////////////////////////
594     Int_t i,j;
595
596     *os << fDetectorIndex << " ";
597     for(i=0;i<3;i++) *os << fid[i]   << " ";
598     for(i=0;i<3;i++) *os << frot[i]  << " ";
599     for(i=0;i<3;i++) *os << ftran[i] << " ";
600     for(i=0;i<3;i++)for(j=0;j<3;j++)  *os << fm[i][j] << " ";
601     *os << endl;
602     return;
603 }
604 //----------------------------------------------------------------------
605 void AliITSgeomMatrix::read(istream *is){
606 ////////////////////////////////////////////////////////////////////////
607 // Standard input format for this class.
608 ////////////////////////////////////////////////////////////////////////
609     Int_t i,j;
610
611     *is >> fDetectorIndex;
612     for(i=0;i<3;i++) *is >> fid[i];
613     for(i=0;i<3;i++) *is >> frot[i];
614     for(i=0;i<3;i++) *is >> ftran[i];
615     for(i=0;i<3;i++)for(j=0;j<3;j++)  *is >> fm[i][j];
616     return;
617 }
618 //----------------------------------------------------------------------
619 ostream &operator<<(ostream &os,AliITSgeomMatrix &p){
620 ////////////////////////////////////////////////////////////////////////
621 // Standard output streaming function.
622 ////////////////////////////////////////////////////////////////////////
623
624     p.print(&os);
625     return os;
626 }
627 //----------------------------------------------------------------------
628 istream &operator>>(istream &is,AliITSgeomMatrix &r){
629 ////////////////////////////////////////////////////////////////////////
630 // Standard input streaming function.
631 ////////////////////////////////////////////////////////////////////////
632
633     r.read(&is);
634     return is;
635 }
636 //----------------------------------------------------------------------
637 void AliITSgeomMatrix::Streamer(TBuffer &R__b){
638 ////////////////////////////////////////////////////////////////////////
639 // Stream an object of class AliITSgeomMatrix.
640 ////////////////////////////////////////////////////////////////////////
641
642    UInt_t R__s, R__c;
643    if (R__b.IsReading()) {
644       Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
645       if (R__v==1) {
646          R__b >> fDetectorIndex;
647          R__b.ReadStaticArray(fid);
648          R__b.ReadStaticArray(frot);
649          R__b.ReadStaticArray(ftran);
650          R__b.ReadStaticArray((double*)fm);
651          R__b.CheckByteCount(R__s, R__c, AliITSgeomMatrix::IsA());
652       } // end if R__v
653    } else { // R__b.IsWriting()
654       R__c = R__b.WriteVersion(AliITSgeomMatrix::IsA(), kTRUE);
655       R__b << fDetectorIndex;
656       R__b.WriteArray(fid, 3);
657       R__b.WriteArray(frot, 3);
658       R__b.WriteArray(ftran, 3);
659       R__b.WriteArray((double*)fm, 9);
660       R__b.SetByteCount(R__c, kTRUE);
661    } // end if R__b.IsReading()||IsWriting()
662 }
663 //______________________________________________________________________