]> git.uio.no Git - u/mrichter/AliRoot.git/blob - STEER/AliAlignObj.cxx
Transformations for rotated geometry of st345 (Gines)
[u/mrichter/AliRoot.git] / STEER / AliAlignObj.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 //   Implementation of the alignment object class through the abstract
18 //  class AliAlignObj. From it two derived concrete representation of
19 //  alignment object class (AliAlignObjAngles, AliAlignObjMatrix) are
20 //  derived in separate files.
21 //-----------------------------------------------------------------
22 /*****************************************************************************
23  * AliAlignObjAngles: derived alignment class storing alignment information  *
24  *   for a single volume in form of three doubles for the translation        *
25  *   and three doubles for the rotation expressed with the euler angles      *
26  *   in the xyz-convention (http://mathworld.wolfram.com/EulerAngles.html),  *
27  *   also known as roll, pitch, yaw. PLEASE NOTE THE ANGLES SIGNS ARE        *
28  *   INVERSE WITH RESPECT TO THIS REFERENCE!!! In this way the representation*
29  *   is fully consistent with the TGeo Rotation methods.                     *
30  *****************************************************************************/
31
32 #include <TGeoManager.h>
33 #include <TGeoPhysicalNode.h>
34
35 #include "AliAlignObj.h"
36 #include "AliTrackPointArray.h"
37 #include "AliLog.h"
38  
39 ClassImp(AliAlignObj)
40
41 Int_t AliAlignObj::fgLayerSize[kLastLayer - kFirstLayer] = {
42   80, 160,  // ITS SPD
43   84, 176,  // ITS SDD
44   748, 950, // ITS SSD
45   36, 36,   // TPC
46   90, 90, 90, 90, 90, 90,  // TRD
47   1674,     // TOF
48   1, 1,     // PHOS ??
49   7,        // RICH ??
50   1         // MUON ??
51 };
52
53 const char* AliAlignObj::fgLayerName[kLastLayer - kFirstLayer] = {
54   "ITS inner pixels layer", "ITS outer pixels layer",
55   "ITS inner drifts layer", "ITS outer drifts layer",
56   "ITS inner strips layer", "ITS outer strips layer",
57   "TPC inner chambers layer", "TPC outer chambers layer",
58   "TRD chambers layer 1", "TRD chambers layer 2", "TRD chambers layer 3",
59   "TRD chambers layer 4", "TRD chambers layer 5", "TRD chambers layer 6",
60   "TOF layer",
61   "?","?",
62   "RICH layer",
63   "?"
64 };
65
66 TString* AliAlignObj::fgVolPath[kLastLayer - kFirstLayer] = {
67   0x0,0x0,
68   0x0,0x0,
69   0x0,0x0,
70   0x0,0x0,
71   0x0,0x0,0x0,
72   0x0,0x0,0x0,
73   0x0,
74   0x0,0x0,
75   0x0,
76   0x0
77 };
78
79 //_____________________________________________________________________________
80 AliAlignObj::AliAlignObj():
81   fVolUID(0)
82 {
83   // default constructor
84   InitVolPaths();
85 }
86
87 //_____________________________________________________________________________
88 AliAlignObj::AliAlignObj(const AliAlignObj& theAlignObj) :
89   TObject(theAlignObj)
90 {
91   //copy constructor
92   fVolPath = theAlignObj.GetVolPath();
93   fVolUID = theAlignObj.GetVolUID();
94 }
95
96 //_____________________________________________________________________________
97 AliAlignObj &AliAlignObj::operator =(const AliAlignObj& theAlignObj)
98 {
99   // assignment operator
100   if(this==&theAlignObj) return *this;
101   fVolPath = theAlignObj.GetVolPath();
102   fVolUID = theAlignObj.GetVolUID();
103   return *this;
104 }
105
106 //_____________________________________________________________________________
107 AliAlignObj::~AliAlignObj()
108 {
109   // dummy destructor
110 }
111
112 //_____________________________________________________________________________
113 void AliAlignObj::SetVolUID(ELayerID detId, Int_t modId)
114 {
115   // From detector name and module number (according to detector numbering)
116   // build fVolUID, unique numerical identity of that volume inside ALICE
117   // fVolUID is 16 bits, first 5 reserved for detID (32 possible values),
118   // remaining 11 for module ID inside det (2048 possible values).
119   //
120   fVolUID = LayerToVolUID(detId,modId);
121 }
122
123 //_____________________________________________________________________________
124 void AliAlignObj::GetVolUID(ELayerID &layerId, Int_t &modId) const
125 {
126   // From detector name and module number (according to detector numbering)
127   // build fVolUID, unique numerical identity of that volume inside ALICE
128   // fVolUID is 16 bits, first 5 reserved for detID (32 possible values),
129   // remaining 11 for module ID inside det (2048 possible values).
130   //
131   layerId = VolUIDToLayer(fVolUID,modId);
132 }
133
134 //_____________________________________________________________________________
135 void AliAlignObj::AnglesToMatrix(const Double_t *angles, Double_t *rot) const
136 {
137   // Calculates the rotation matrix using the 
138   // Euler angles in "x y z" notation
139   Double_t degrad = TMath::DegToRad();
140   Double_t sinpsi = TMath::Sin(degrad*angles[0]);
141   Double_t cospsi = TMath::Cos(degrad*angles[0]);
142   Double_t sinthe = TMath::Sin(degrad*angles[1]);
143   Double_t costhe = TMath::Cos(degrad*angles[1]);
144   Double_t sinphi = TMath::Sin(degrad*angles[2]);
145   Double_t cosphi = TMath::Cos(degrad*angles[2]);
146
147   rot[0] =  costhe*cosphi;
148   rot[1] = -costhe*sinphi;
149   rot[2] =  sinthe;
150   rot[3] =  sinpsi*sinthe*cosphi + cospsi*sinphi;
151   rot[4] = -sinpsi*sinthe*sinphi + cospsi*cosphi;
152   rot[5] = -costhe*sinpsi;
153   rot[6] = -cospsi*sinthe*cosphi + sinpsi*sinphi;
154   rot[7] =  cospsi*sinthe*sinphi + sinpsi*cosphi;
155   rot[8] =  costhe*cospsi;
156 }
157
158 //_____________________________________________________________________________
159 Bool_t AliAlignObj::MatrixToAngles(const Double_t *rot, Double_t *angles) const
160 {
161   // Calculates the Euler angles in "x y z" notation
162   // using the rotation matrix
163   if(rot[0]<1e-7 || rot[8]<1e-7) return kFALSE;
164   Double_t raddeg = TMath::RadToDeg();
165   angles[0]=raddeg*TMath::ATan2(-rot[5],rot[8]);
166   angles[1]=raddeg*TMath::ASin(rot[2]);
167   angles[2]=raddeg*TMath::ATan2(-rot[1],rot[0]);
168   return kTRUE;
169 }
170
171 //______________________________________________________________________________
172 void AliAlignObj::Transform(AliTrackPoint &p) const
173 {
174   // The method transforms the space-point coordinates using the
175   // transformation matrix provided by the AliAlignObj
176   // The covariance matrix is not affected since we assume
177   // that the transformations are sufficiently small
178
179   if (fVolUID != p.GetVolumeID())
180     AliWarning(Form("Alignment object ID is not equal to the space-point ID (%d != %d)",fVolUID,p.GetVolumeID())); 
181
182   TGeoHMatrix m;
183   GetMatrix(m);
184   Double_t *rot = m.GetRotationMatrix();
185   Double_t *tr  = m.GetTranslation();
186
187   Float_t xyzin[3],xyzout[3];
188   p.GetXYZ(xyzin);
189   for (Int_t i = 0; i < 3; i++)
190     xyzout[i] = tr[i]+
191                 xyzin[0]*rot[3*i]+
192                 xyzin[1]*rot[3*i+1]+
193                 xyzin[2]*rot[3*i+2];
194   p.SetXYZ(xyzout);
195   
196 }
197
198 //______________________________________________________________________________
199 void AliAlignObj::Transform(AliTrackPointArray &array) const
200 {
201   AliTrackPoint p;
202   for (Int_t i = 0; i < array.GetNPoints(); i++) {
203     array.GetPoint(p,i);
204     Transform(p);
205     array.AddPoint(i,&p);
206   }
207 }
208
209 //_____________________________________________________________________________
210 void AliAlignObj::Print(Option_t *) const
211 {
212   // Print the contents of the
213   // alignment object in angles and
214   // matrix representations
215   Double_t tr[3];
216   GetTranslation(tr);
217   Double_t angles[3];
218   GetAngles(angles);
219   TGeoHMatrix m;
220   GetMatrix(m);
221   const Double_t *rot = m.GetRotationMatrix();
222 //   printf("Volume=%s ID=%u\n", GetVolPath(),GetVolUID());
223   ELayerID layerId;
224   Int_t modId;
225   GetVolUID(layerId,modId);
226   printf("Volume=%s LayerID=%d ModuleID=%d\n", GetVolPath(),layerId,modId);
227   printf("%12.6f%12.6f%12.6f    Tx = %12.6f    Psi   = %12.6f\n", rot[0], rot[1], rot[2], tr[0], angles[0]);
228   printf("%12.6f%12.6f%12.6f    Ty = %12.6f    Theta = %12.6f\n", rot[3], rot[4], rot[5], tr[1], angles[1]);
229   printf("%12.6f%12.6f%12.6f    Tz = %12.6f    Phi   = %12.6f\n", rot[6], rot[7], rot[8], tr[2], angles[2]);
230
231 }
232
233 //_____________________________________________________________________________
234 UShort_t AliAlignObj::LayerToVolUID(ELayerID layerId, Int_t modId)
235 {
236   // From detector (layer) name and module number (according to detector numbering)
237   // build fVolUID, unique numerical identity of that volume inside ALICE
238   // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
239   // remaining 11 for module ID inside det (2048 possible values).
240   //
241   return ((UShort_t(layerId) << 11) | UShort_t(modId));
242 }
243
244 //_____________________________________________________________________________
245 AliAlignObj::ELayerID AliAlignObj::VolUIDToLayer(UShort_t voluid, Int_t &modId)
246 {
247   // From detector (layer) name and module number (according to detector numbering)
248   // build fVolUID, unique numerical identity of that volume inside ALICE
249   // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
250   // remaining 11 for module ID inside det (2048 possible values).
251   //
252   modId = voluid & 0x7ff;
253
254   return VolUIDToLayer(voluid);
255 }
256
257 //_____________________________________________________________________________
258 AliAlignObj::ELayerID AliAlignObj::VolUIDToLayer(UShort_t voluid)
259 {
260   // From detector (layer) name and module number (according to detector numbering)
261   // build fVolUID, unique numerical identity of that volume inside ALICE
262   // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
263   // remaining 11 for module ID inside det (2048 possible values).
264   //
265   return ELayerID((voluid >> 11) & 0x1f);
266 }
267
268 //_____________________________________________________________________________
269 Bool_t AliAlignObj::ApplyToGeometry()
270 {
271   // Apply the current alignment object
272   // to the TGeo geometry
273
274   if (!gGeoManager || !gGeoManager->IsClosed()) {
275     AliError("Can't apply the alignment object! gGeoManager doesn't exist or it is still opened!");
276     return kFALSE;
277   }
278   
279   const char* volpath = GetVolPath();
280   TGeoPhysicalNode* node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(volpath);
281   if (!node) {
282     AliError(Form("Volume path %s not valid!",volpath));
283     return kFALSE;
284   }
285   if (node->IsAligned()) {
286     AliWarning(Form("Volume %s has been already misaligned!",volpath));
287     return kFALSE;
288   }
289
290   TGeoHMatrix align,gprime;
291   gprime = *node->GetMatrix();
292   GetMatrix(align);
293   gprime.MultiplyLeft(&align);
294   TGeoHMatrix *ginv = new TGeoHMatrix;
295   TGeoHMatrix *g = node->GetMatrix(node->GetLevel()-1);
296   *ginv = g->Inverse();
297   *ginv *= gprime;
298   AliAlignObj::ELayerID layerId; // unique identity for volume in the alobj
299   Int_t modId; // unique identity for volume in the alobj
300   GetVolUID(layerId, modId);
301   AliInfo(Form("Aligning volume %s of detector layer %d with local ID %d",volpath,layerId,modId));
302   node->Align(ginv);
303
304   return kTRUE;
305 }
306
307 //_____________________________________________________________________________
308 Bool_t AliAlignObj::GetFromGeometry(const char *path, AliAlignObj &alobj)
309 {
310   // Get the alignment object which correspond
311   // to the TGeo volume defined by the 'path'.
312   // The method is extremely slow due to the
313   // searching by string. Therefore it should
314   // be used with great care!!
315
316   // Reset the alignment object
317   alobj.SetPars(0,0,0,0,0,0);
318   alobj.SetVolPath(path);
319
320   if (!gGeoManager || !gGeoManager->IsClosed()) {
321     AliErrorClass("Can't get the alignment object! gGeoManager doesn't exist or it is still opened!");
322     return kFALSE;
323   }
324
325   if (!gGeoManager->GetListOfPhysicalNodes()) {
326     AliErrorClass("Can't get the alignment object! gGeoManager doesn't contain any aligned nodes!");
327     return kFALSE;
328   }
329
330   TObjArray* nodesArr = gGeoManager->GetListOfPhysicalNodes();
331   TGeoPhysicalNode* node = NULL;
332   for (Int_t iNode = 0; iNode < nodesArr->GetEntriesFast(); iNode++) {
333     node = (TGeoPhysicalNode*) nodesArr->UncheckedAt(iNode);
334     const char *nodePath = node->GetName();
335     if (strcmp(path,nodePath) == 0) break;
336   }
337   if (!node) {
338     AliWarningClass(Form("Volume path %s not found!",path));
339     return kFALSE;
340   }
341
342   TGeoHMatrix align,gprime,g,ginv,l;
343   gprime = *node->GetMatrix();
344   l = *node->GetOriginalMatrix();
345   g = *node->GetMatrix(node->GetLevel()-1);
346   g *= l;
347   ginv = g.Inverse();
348   align = gprime * ginv;
349   alobj.SetMatrix(align);
350
351   return kTRUE;
352 }
353
354 //_____________________________________________________________________________
355 void AliAlignObj::InitVolPaths()
356 {
357   // Initialize the LUTs which contain
358   // the TGeo volume paths for each
359   // alignable volume. The LUTs are
360   // static, so they are created during
361   // the creation of the first intance
362   // of AliAlignObj
363
364   if (fgVolPath[0]) return;
365
366   for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++)
367     fgVolPath[iLayer] = new TString[fgLayerSize[iLayer]];
368
369   /*********************       SPD layer1  ***********************/
370   {
371     Int_t modnum = 0;
372     TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT12_1/I12B_"; //".../I12A_"
373     TString str1 = "/I10B_";    //"/I10A_";
374     TString str2 = "/I107_";    //"/I103_"
375     //    TString str3 = "/I101_1/ITS1_1";
376     TString volpath, volpath1, volpath2;
377
378     for(Int_t c1 = 1; c1<=10; c1++){
379       volpath = str0;
380       volpath += c1;
381       volpath += str1;
382       for(Int_t c2 =1; c2<=2; c2++){
383         volpath1 = volpath;
384         volpath1 += c2;
385         volpath1 += str2;
386         for(Int_t c3 =1; c3<=4; c3++){
387           volpath2 = volpath1;
388           volpath2 += c3;
389           //      volpath2 += str3;
390           fgVolPath[kSPD1-kFirstLayer][modnum] = volpath2.Data();
391           modnum++;
392         }
393       }
394     }
395   }
396   
397   /*********************       SPD layer2  ***********************/
398   {
399     Int_t modnum = 0;
400     TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT12_1/I12B_";  //".../I12A_"
401     TString str1 = "/I20B_";  //"/I20A"
402     TString str2 = "/I1D7_";  //"/I1D3"
403     //    TString str3 = "/I1D1_1/ITS2_1";
404     TString volpath, volpath1, volpath2;
405
406     for(Int_t c1 = 1; c1<=10; c1++){
407       volpath = str0;
408       volpath += c1;
409       volpath += str1;
410       for(Int_t c2 =1; c2<=4; c2++){
411         volpath1 = volpath;
412         volpath1 += c2;
413         volpath1 += str2;
414         for(Int_t c3 =1; c3<=4; c3++){
415           volpath2 = volpath1;
416           volpath2 += c3;
417           //      volpath2 += str3;
418           fgVolPath[kSPD2-kFirstLayer][modnum] = volpath2.Data();
419           modnum++;
420         }
421       }
422     }
423   }
424
425   /*********************       SDD layer1  ***********************/
426   {
427     Int_t modnum=0;
428     TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT34_1/I004_";
429     TString str1 = "/I302_";
430     //    TString str2 = "/ITS3_1";
431     TString volpath, volpath1;
432
433     for(Int_t c1 = 1; c1<=14; c1++){
434       volpath = str0;
435       volpath += c1;
436       volpath += str1;
437       for(Int_t c2 =1; c2<=6; c2++){
438         volpath1 = volpath;
439         volpath1 += c2;
440         //      volpath1 += str2;
441         fgVolPath[kSDD1-kFirstLayer][modnum] = volpath1.Data();
442         modnum++;
443       }
444     }
445   }
446
447   /*********************       SDD layer2  ***********************/
448   {
449     Int_t modnum=0;
450     TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT34_1/I005_";
451     TString str1 = "/I402_";
452     //    TString str2 = "/ITS4_1";
453     TString volpath, volpath1;
454
455     for(Int_t c1 = 1; c1<=22; c1++){
456       volpath = str0;
457       volpath += c1;
458       volpath += str1;
459       for(Int_t c2 = 1; c2<=8; c2++){
460         volpath1 = volpath;
461         volpath1 += c2;
462         //      volpath1 += str2;
463         fgVolPath[kSDD2-kFirstLayer][modnum] = volpath1.Data();
464         modnum++;
465       }
466     }
467   }
468
469   /*********************       SSD layer1  ***********************/
470   {
471     Int_t modnum=0;
472     TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT56_1/I565_";
473     TString str1 = "/I562_";
474     //    TString str2 = "/ITS5_1";
475     TString volpath, volpath1;
476
477     for(Int_t c1 = 1; c1<=34; c1++){
478       volpath = str0;
479       volpath += c1;
480       volpath += str1;
481       for(Int_t c2 = 1; c2<=22; c2++){
482         volpath1 = volpath;
483         volpath1 += c2;
484         //      volpath1 += str2;
485         fgVolPath[kSSD1-kFirstLayer][modnum] = volpath1.Data();
486         modnum++;
487       }
488     }
489   }
490
491   /*********************       SSD layer1  ***********************/
492   {
493     Int_t modnum=0;
494     TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT56_1/I569_";
495     TString str1 = "/I566_";
496     //    TString str2 = "/ITS6_1";
497     TString volpath, volpath1;
498
499     for(Int_t c1 = 1; c1<=38; c1++){
500       volpath = str0;
501       volpath += c1;
502       volpath += str1;
503       for(Int_t c2 = 1; c2<=25; c2++){
504         volpath1 = volpath;
505         volpath1 += c2;
506         //      volpath1 += str2;
507         fgVolPath[kSSD2-kFirstLayer][modnum] = volpath1.Data();
508         modnum++;
509       }
510     }
511   }
512
513   /*********************       TOF layer   ***********************/
514   {
515     Int_t nstrA=15;
516     Int_t nstrB=19;
517     Int_t nstrC=20;
518     Int_t nStripSec=nstrA+2*nstrB+2*nstrC;
519
520     for (Int_t modnum=0; modnum < 1674; modnum++) {
521
522       Int_t sector = modnum/nStripSec;
523
524       Char_t  string1[100];
525       Char_t  string2[100];
526
527       Int_t icopy=-1;
528       if(sector<2){
529         icopy=sector+1;
530         sprintf(string1,"/ALIC_1/B077_1/B075_%i/BTO3_1",icopy);
531       }
532       else if(sector<11){
533         icopy=sector-2;
534         sprintf(string1,"/ALIC_1/B077_1/B071_%i/BTO1_1",icopy);
535       }
536       else if(sector==11 || sector==12){
537         icopy=sector-10;
538         sprintf(string1,"/ALIC_1/B077_1/B074_%i/BTO2_1",icopy);
539       }
540       else {
541         icopy=sector-4;
542         sprintf(string1,"/ALIC_1/B077_1/B071_%i/BTO1_1",icopy);
543       }
544
545       Int_t strInSec=modnum%nStripSec;
546
547       if( strInSec < nstrC){
548         icopy= strInSec+1;
549         sprintf(string2,"FTOC_1/FLTC_1/FSTR_%i",icopy);
550       }
551       else if(strInSec< nstrC+nstrB){
552  
553         icopy= strInSec-nstrC+1;
554         sprintf(string2,"FTOB_1/FLTB_1/FSTR_%i",icopy);
555
556       }
557       else if(strInSec< nstrC+nstrB+nstrA){   
558
559         icopy= strInSec-(nstrC+nstrB)+1;
560         sprintf(string2,"FTOA_1/FLTA_1/FSTR_%i",icopy);
561  
562       }
563       else if(strInSec< nstrC+2*nstrB+nstrA){ 
564
565         icopy= strInSec-(nstrC+nstrB+nstrA)+1;
566         sprintf(string2,"FTOB_2/FLTB_2/FSTR_%i",icopy);
567
568       }
569       else  { 
570
571         icopy= strInSec-(nstrC+2*nstrB+nstrA)+1;
572         sprintf(string2,"FTOC_2/FLTC_2/FSTR_%i",icopy);
573
574       }
575   
576       Char_t  path[100];
577       sprintf(path,"%s/%s",string1,string2); 
578       //      printf("%d  %s\n",modnum,path);
579       fgVolPath[kTOF-kFirstLayer][modnum] = path;
580     }
581   } 
582 }