]> git.uio.no Git - u/mrichter/AliRoot.git/blob - STEER/AliAlignObj.cxx
EMCAL geometry can be created independently form anything now
[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 /* $Id$ */
17
18 //-----------------------------------------------------------------
19 //  Implementation of the alignment object class, holding the alignment
20 //  constants for a single volume, through the abstract class AliAlignObj.
21 //  From it two derived concrete representation of alignment object class
22 //  (AliAlignObjAngles, AliAlignObjMatrix) are derived in separate files.
23 //-----------------------------------------------------------------
24 #include <TGeoManager.h>
25 #include <TGeoPhysicalNode.h>
26 #include <TMath.h>
27
28 #include "AliAlignObj.h"
29 #include "AliTrackPointArray.h"
30 #include "AliLog.h"
31 #include "AliAlignObjAngles.h"
32  
33 ClassImp(AliAlignObj)
34
35 Int_t AliAlignObj::fgLayerSize[kLastLayer - kFirstLayer] = {
36   80, 160,  // ITS SPD first and second layer
37   84, 176,  // ITS SDD first and second layer
38   748, 950, // ITS SSD first and second layer
39   36, 36,   // TPC inner and outer chambers
40   90, 90, 90, 90, 90, 90,  // 6 TRD chambers' layers
41   1638,     // TOF
42   1, 1,     // PHOS ??
43   7,        // HMPID ??
44   1         // MUON ??
45 };
46
47 const char* AliAlignObj::fgLayerName[kLastLayer - kFirstLayer] = {
48   "ITS inner pixels layer", "ITS outer pixels layer",
49   "ITS inner drifts layer", "ITS outer drifts layer",
50   "ITS inner strips layer", "ITS outer strips layer",
51   "TPC inner chambers layer", "TPC outer chambers layer",
52   "TRD chambers layer 1", "TRD chambers layer 2", "TRD chambers layer 3",
53   "TRD chambers layer 4", "TRD chambers layer 5", "TRD chambers layer 6",
54   "TOF layer",
55   "?","?",
56   "HMPID layer",
57   "?"
58 };
59
60 TString* AliAlignObj::fgVolPath[kLastLayer - kFirstLayer] = {
61   0x0,0x0,
62   0x0,0x0,
63   0x0,0x0,
64   0x0,0x0,
65   0x0,0x0,0x0,
66   0x0,0x0,0x0,
67   0x0,
68   0x0,0x0,
69   0x0,
70   0x0
71 };
72
73 AliAlignObj** AliAlignObj::fgAlignObjs[kLastLayer - kFirstLayer] = {
74   0x0,0x0,
75   0x0,0x0,
76   0x0,0x0,
77   0x0,0x0,
78   0x0,0x0,0x0,
79   0x0,0x0,0x0,
80   0x0,
81   0x0,0x0,
82   0x0,
83   0x0
84 };
85
86 //_____________________________________________________________________________
87 AliAlignObj::AliAlignObj():
88   fVolPath(),
89   fVolUID(0)
90 {
91   // default constructor
92   InitSymNames();
93 }
94
95 //_____________________________________________________________________________
96 AliAlignObj::AliAlignObj(const char* symname, UShort_t voluid) :
97   TObject(),
98   fVolPath(symname),
99   fVolUID(voluid)
100 {
101   // standard constructor
102   //
103 }
104
105 //_____________________________________________________________________________
106 AliAlignObj::AliAlignObj(const AliAlignObj& theAlignObj) :
107   TObject(theAlignObj),
108   fVolPath(theAlignObj.GetSymName()),
109   fVolUID(theAlignObj.GetVolUID())
110 {
111   //copy constructor
112 }
113
114 //_____________________________________________________________________________
115 AliAlignObj &AliAlignObj::operator =(const AliAlignObj& theAlignObj)
116 {
117   // assignment operator
118   if(this==&theAlignObj) return *this;
119   fVolPath = theAlignObj.GetSymName();
120   fVolUID = theAlignObj.GetVolUID();
121   return *this;
122 }
123
124 //_____________________________________________________________________________
125 AliAlignObj &AliAlignObj::operator*=(const AliAlignObj& theAlignObj)
126 {
127   // multiplication operator
128   // The operator can be used to 'combine'
129   // two alignment objects
130   TGeoHMatrix m1;
131   GetMatrix(m1);
132   TGeoHMatrix m2;
133   theAlignObj.GetMatrix(m2);
134   m1.MultiplyLeft(&m2);
135   SetMatrix(m1);
136   return *this;
137 }
138
139 //_____________________________________________________________________________
140 AliAlignObj::~AliAlignObj()
141 {
142   // dummy destructor
143 }
144
145 //_____________________________________________________________________________
146 void AliAlignObj::SetVolUID(ELayerID detId, Int_t modId)
147 {
148   // From detector name and module number (according to detector numbering)
149   // build fVolUID, unique numerical identity of that volume inside ALICE
150   // fVolUID is 16 bits, first 5 reserved for detID (32 possible values),
151   // remaining 11 for module ID inside det (2048 possible values).
152   //
153   fVolUID = LayerToVolUID(detId,modId);
154 }
155
156 //_____________________________________________________________________________
157 void AliAlignObj::GetVolUID(ELayerID &layerId, Int_t &modId) const
158 {
159   // From the fVolUID, unique numerical identity of that volume inside ALICE,
160   // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
161   // remaining 11 for module ID inside det (2048 possible values)), sets
162   // the argument layerId to the identity of the layer to which that volume
163   // belongs and sets the argument modId to the identity of that volume
164   // internally to the layer.
165   //
166   layerId = VolUIDToLayer(fVolUID,modId);
167 }
168
169 //_____________________________________________________________________________
170 Bool_t AliAlignObj::GetPars(Double_t tr[], Double_t angles[]) const
171 {
172   GetTranslation(tr);
173   return GetAngles(angles);
174 }
175
176 //_____________________________________________________________________________
177 Int_t AliAlignObj::GetLevel() const
178 {
179   // Return the geometry level of the alignable volume to which
180   // the alignment object is associated; this is the number of
181   // slashes in the corresponding volume path
182   //
183   if(!gGeoManager){
184     AliWarning("gGeoManager doesn't exist or it is still opened: unable to return meaningful level value.");
185     return (-1);
186   }
187   const char* symname = GetSymName();
188   const char* path;
189   TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
190   if(pne){
191     path = pne->GetTitle();
192   }else{
193     path = symname;
194   }
195
196   TString path_str = path;
197   if(path_str[0]!='/') path_str.Prepend('/');
198   return path_str.CountChar('/');
199 }
200
201 //_____________________________________________________________________________
202 Int_t AliAlignObj::Compare(const TObject *obj) const
203 {
204   // Compare the levels of two
205   // alignment objects
206   // Used in the sorting during
207   // the application of alignment
208   // objects to the geometry
209   //
210   Int_t level = GetLevel();
211   Int_t level2 = ((AliAlignObj *)obj)->GetLevel();
212   if (level == level2)
213     return 0;
214   else
215     return ((level > level2) ? 1 : -1);
216 }
217
218 //_____________________________________________________________________________
219 void AliAlignObj::AnglesToMatrix(const Double_t *angles, Double_t *rot) const
220 {
221   // Calculates the rotation matrix using the 
222   // Euler angles in "x y z" notation
223   //
224   Double_t degrad = TMath::DegToRad();
225   Double_t sinpsi = TMath::Sin(degrad*angles[0]);
226   Double_t cospsi = TMath::Cos(degrad*angles[0]);
227   Double_t sinthe = TMath::Sin(degrad*angles[1]);
228   Double_t costhe = TMath::Cos(degrad*angles[1]);
229   Double_t sinphi = TMath::Sin(degrad*angles[2]);
230   Double_t cosphi = TMath::Cos(degrad*angles[2]);
231
232   rot[0] =  costhe*cosphi;
233   rot[1] = -costhe*sinphi;
234   rot[2] =  sinthe;
235   rot[3] =  sinpsi*sinthe*cosphi + cospsi*sinphi;
236   rot[4] = -sinpsi*sinthe*sinphi + cospsi*cosphi;
237   rot[5] = -costhe*sinpsi;
238   rot[6] = -cospsi*sinthe*cosphi + sinpsi*sinphi;
239   rot[7] =  cospsi*sinthe*sinphi + sinpsi*cosphi;
240   rot[8] =  costhe*cospsi;
241 }
242
243 //_____________________________________________________________________________
244 Bool_t AliAlignObj::MatrixToAngles(const Double_t *rot, Double_t *angles) const
245 {
246   // Calculates the Euler angles in "x y z" notation
247   // using the rotation matrix
248   // Returns false in case the rotation angles can not be
249   // extracted from the matrix
250   //
251   if(TMath::Abs(rot[0])<1e-7 || TMath::Abs(rot[8])<1e-7) {
252     AliError("Failed to extract roll-pitch-yall angles!");
253     return kFALSE;
254   }
255   Double_t raddeg = TMath::RadToDeg();
256   angles[0]=raddeg*TMath::ATan2(-rot[5],rot[8]);
257   angles[1]=raddeg*TMath::ASin(rot[2]);
258   angles[2]=raddeg*TMath::ATan2(-rot[1],rot[0]);
259   return kTRUE;
260 }
261
262 //______________________________________________________________________________
263 void AliAlignObj::Transform(AliTrackPoint &p) const
264 {
265   // The method transforms the space-point coordinates using the
266   // transformation matrix provided by the AliAlignObj
267   // The covariance matrix is not affected since we assume
268   // that the transformations are sufficiently small
269   //
270   if (fVolUID != p.GetVolumeID())
271     AliWarning(Form("Alignment object ID is not equal to the space-point ID (%d != %d)",fVolUID,p.GetVolumeID())); 
272
273   TGeoHMatrix m;
274   GetMatrix(m);
275   Double_t *rot = m.GetRotationMatrix();
276   Double_t *tr  = m.GetTranslation();
277
278   Float_t xyzin[3],xyzout[3];
279   p.GetXYZ(xyzin);
280   for (Int_t i = 0; i < 3; i++)
281     xyzout[i] = tr[i]+
282                 xyzin[0]*rot[3*i]+
283                 xyzin[1]*rot[3*i+1]+
284                 xyzin[2]*rot[3*i+2];
285   p.SetXYZ(xyzout);
286   
287 }
288
289 //_____________________________________________________________________________
290 void AliAlignObj::Transform(AliTrackPointArray &array) const
291 {
292   // This method is used to transform all the track points
293   // from the input AliTrackPointArray
294   // 
295   AliTrackPoint p;
296   for (Int_t i = 0; i < array.GetNPoints(); i++) {
297     array.GetPoint(p,i);
298     Transform(p);
299     array.AddPoint(i,&p);
300   }
301 }
302
303 //_____________________________________________________________________________
304 void AliAlignObj::Print(Option_t *) const
305 {
306   // Print the contents of the
307   // alignment object in angles and
308   // matrix representations
309   //
310   Double_t tr[3];
311   GetTranslation(tr);
312   Double_t angles[3];
313   GetAngles(angles);
314   TGeoHMatrix m;
315   GetMatrix(m);
316   const Double_t *rot = m.GetRotationMatrix();
317
318   printf("Volume=%s\n",GetSymName());
319   if (GetVolUID() != 0) {
320     ELayerID layerId;
321     Int_t modId;
322     GetVolUID(layerId,modId);
323     printf("VolumeID=%d LayerID=%d ( %s ) ModuleID=%d\n", GetVolUID(),layerId,LayerName(layerId),modId);
324   }
325   printf("%12.8f%12.8f%12.8f    Tx = %12.8f    Psi   = %12.8f\n", rot[0], rot[1], rot[2], tr[0], angles[0]);
326   printf("%12.8f%12.8f%12.8f    Ty = %12.8f    Theta = %12.8f\n", rot[3], rot[4], rot[5], tr[1], angles[1]);
327   printf("%12.8f%12.8f%12.8f    Tz = %12.8f    Phi   = %12.8f\n", rot[6], rot[7], rot[8], tr[2], angles[2]);
328
329 }
330
331 //_____________________________________________________________________________
332 Int_t AliAlignObj::LayerSize(Int_t layerId)
333 {
334   // Get the layer size for layer corresponding to layerId.
335   // Implemented only for ITS,TPC,TRD,TOF and HMPID
336   //
337   if (layerId < kFirstLayer || layerId >= kLastLayer) {
338     AliErrorClass(Form("Invalid layer index %d ! Layer range is (%d -> %d) !",layerId,kFirstLayer,kLastLayer));
339     return 0;
340   }
341   else {
342     return fgLayerSize[layerId - kFirstLayer];
343  }
344 }
345
346 //_____________________________________________________________________________
347 const char* AliAlignObj::LayerName(Int_t layerId)
348 {
349   // Get the layer name corresponding to layerId.
350   // Implemented only for ITS,TPC,TRD,TOF and HMPID
351   //
352   if (layerId < kFirstLayer || layerId >= kLastLayer) {
353     AliErrorClass(Form("Invalid layer index %d ! Layer range is (%d -> %d) !",layerId,kFirstLayer,kLastLayer));
354     return "Invalid Layer!";
355   }
356   else {
357     return fgLayerName[layerId - kFirstLayer];
358  }
359 }
360
361 //_____________________________________________________________________________
362 UShort_t AliAlignObj::LayerToVolUID(ELayerID layerId, Int_t modId)
363 {
364   // From detector (layer) name and module number (according to detector
365   // internal numbering) build the unique numerical identity of that volume
366   // inside ALICE
367   // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
368   // remaining 11 for module ID inside det (2048 possible values).
369   //
370   return ((UShort_t(layerId) << 11) | UShort_t(modId));
371 }
372
373 //_____________________________________________________________________________
374 UShort_t AliAlignObj::LayerToVolUID(Int_t   layerId, Int_t modId)
375 {
376   // From detector (layer) name and module number (according to detector
377   // internal numbering) build the unique numerical identity of that volume
378   // inside ALICE
379   // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
380   // remaining 11 for module ID inside det (2048 possible values).
381   //
382   return ((UShort_t(layerId) << 11) | UShort_t(modId));
383 }
384
385 //_____________________________________________________________________________
386 AliAlignObj::ELayerID AliAlignObj::VolUIDToLayer(UShort_t voluid, Int_t &modId)
387 {
388   // From voluid, unique numerical identity of that volume inside ALICE,
389   // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
390   // remaining 11 for module ID inside det (2048 possible values)), return
391   // the identity of the layer to which that volume belongs and sets the
392   // argument modId to the identity of that volume internally to the layer.
393   //
394   modId = voluid & 0x7ff;
395
396   return VolUIDToLayer(voluid);
397 }
398
399 //_____________________________________________________________________________
400 AliAlignObj::ELayerID AliAlignObj::VolUIDToLayer(UShort_t voluid)
401 {
402   // From voluid, unique numerical identity of that volume inside ALICE,
403   // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
404   // remaining 11 for module ID inside det (2048 possible values)), return
405   // the identity of the layer to which that volume belongs
406   //
407   return ELayerID((voluid >> 11) & 0x1f);
408 }
409
410 //_____________________________________________________________________________
411 void AliAlignObj::SetPars(Double_t x, Double_t y, Double_t z,
412                           Double_t psi, Double_t theta, Double_t phi)
413 {
414   // Set the global delta transformation by passing 3 angles (expressed in
415   // degrees) and 3 shifts (in centimeters)
416   // 
417   SetTranslation(x,y,z);
418   SetRotation(psi,theta,phi);
419 }
420
421 //_____________________________________________________________________________
422 Bool_t AliAlignObj::SetLocalPars(Double_t x, Double_t y, Double_t z,
423                                  Double_t psi, Double_t theta, Double_t phi)
424 {
425   // Set the global delta transformation by passing the parameters
426   // for the local delta transformation (3 shifts and 3 angles).
427   // In case that the TGeo was not initialized or not closed,
428   // returns false and the object parameters are not set.
429   //
430   TGeoHMatrix m;
431   Double_t tr[3] = {x, y, z};
432   m.SetTranslation(tr);
433   Double_t angles[3] = {psi, theta, phi};
434   Double_t rot[9];
435   AnglesToMatrix(angles,rot);
436   m.SetRotation(rot);
437
438   return SetLocalMatrix(m);
439
440 }
441
442 //_____________________________________________________________________________
443 Bool_t AliAlignObj::SetLocalTranslation(Double_t x, Double_t y, Double_t z)
444 {
445   // Set the global delta transformation by passing the three shifts giving
446   // the translation in the local reference system of the alignable
447   // volume (known by TGeo geometry).
448   // In case that the TGeo was not initialized or not closed,
449   // returns false and the object parameters are not set.
450   //
451   TGeoHMatrix m;
452   Double_t tr[3] = {x, y, z};
453   m.SetTranslation(tr);
454
455   return SetLocalMatrix(m);
456
457 }
458
459 //_____________________________________________________________________________
460 Bool_t AliAlignObj::SetLocalTranslation(const TGeoMatrix& m)
461 {
462   // Set the global delta transformation by passing the matrix of
463   // the local delta transformation and taking its translational part
464   // In case that the TGeo was not initialized or not closed,
465   // returns false and the object parameters are not set.
466   //
467   const Double_t* tr = m.GetTranslation();
468   TGeoHMatrix mtr;
469   mtr.SetTranslation(tr);
470
471   return SetLocalMatrix(mtr);
472
473 }
474
475 //_____________________________________________________________________________
476 Bool_t AliAlignObj::SetLocalRotation(Double_t psi, Double_t theta, Double_t phi)
477 {
478   // Set the global delta transformation by passing the three angles giving
479   // the rotation in the local reference system of the alignable
480   // volume (known by TGeo geometry).
481   // In case that the TGeo was not initialized or not closed,
482   // returns false and the object parameters are not set.
483   //
484   TGeoHMatrix m;
485   Double_t angles[3] = {psi, theta, phi};
486   Double_t rot[9];
487   AnglesToMatrix(angles,rot);
488   m.SetRotation(rot);
489
490   return SetLocalMatrix(m);
491
492 }
493
494 //_____________________________________________________________________________
495 Bool_t AliAlignObj::SetLocalRotation(const TGeoMatrix& m)
496 {
497   // Set the global delta transformation by passing the matrix of
498   // the local delta transformation and taking its rotational part
499   // In case that the TGeo was not initialized or not closed,
500   // returns false and the object parameters are not set.
501   //
502   TGeoHMatrix rotm;
503   const Double_t* rot = m.GetRotationMatrix();
504   rotm.SetRotation(rot);
505
506   return SetLocalMatrix(rotm);
507
508 }
509
510 //_____________________________________________________________________________
511 Bool_t AliAlignObj::SetLocalMatrix(const TGeoMatrix& m)
512 {
513   // Set the global delta transformation by passing the TGeo matrix
514   // for the local delta transformation.
515   // In case that the TGeo was not initialized or not closed,
516   // returns false and the object parameters are not set.
517   //
518   if (!gGeoManager || !gGeoManager->IsClosed()) {
519     AliError("Can't set the alignment object parameters! gGeoManager doesn't exist or it is still opened!");
520     return kFALSE;
521   }
522
523   const char* symname = GetSymName();
524   TGeoPhysicalNode* node;
525   TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
526   if(pne){
527     node = gGeoManager->MakeAlignablePN(pne);
528   }else{
529     AliWarning(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as volume path!",symname));
530     node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(symname);
531   }
532
533   if (!node) {
534     AliError(Form("Volume name or path %s not valid!",symname));
535     return kFALSE;
536   }
537   if (node->IsAligned())
538     AliWarning(Form("Volume %s has been already misaligned!",symname));
539
540   TGeoHMatrix m1;
541   const Double_t *tr = m.GetTranslation();
542   m1.SetTranslation(tr);
543   const Double_t* rot = m.GetRotationMatrix();
544   m1.SetRotation(rot);
545
546   TGeoHMatrix align,gprime,gprimeinv;
547   gprime = *node->GetMatrix();
548   gprimeinv = gprime.Inverse();
549   m1.Multiply(&gprimeinv);
550   m1.MultiplyLeft(&gprime);
551
552   return SetMatrix(m1);
553 }
554
555 //_____________________________________________________________________________
556 Bool_t AliAlignObj::SetMatrix(const TGeoMatrix& m)
557 {
558   // Set the global delta transformation by passing the TGeoMatrix
559   // for it
560   //
561   SetTranslation(m);
562   return SetRotation(m);
563 }
564
565 //_____________________________________________________________________________
566 Bool_t AliAlignObj::GetLocalPars(Double_t transl[], Double_t angles[]) const
567 {
568   // Get the translations and angles (in degrees) expressing the
569   // local delta transformation.
570   // In case that the TGeo was not initialized or not closed,
571   // returns false and the object parameters are not set.
572   //
573   if(!GetLocalTranslation(transl)) return kFALSE;
574   return GetLocalAngles(angles);
575 }
576
577 //_____________________________________________________________________________
578 Bool_t AliAlignObj::GetLocalTranslation(Double_t* tr) const
579 {
580   // Get the 3 shifts giving the translational part of the local
581   // delta transformation.
582   // In case that the TGeo was not initialized or not closed,
583   // returns false and the object parameters are not set.
584   //
585   TGeoHMatrix ml;
586   if(!GetLocalMatrix(ml)) return kFALSE;
587   const Double_t* transl;
588   transl = ml.GetTranslation();
589   tr[0]=transl[0];
590   tr[1]=transl[1];
591   tr[2]=transl[2];
592   return kTRUE;
593 }
594
595 //_____________________________________________________________________________
596 Bool_t AliAlignObj::GetLocalAngles(Double_t* angles) const
597 {
598   // Get the 3 angles giving the rotational part of the local
599   // delta transformation.
600   // In case that the TGeo was not initialized or not closed,
601   // returns false and the object parameters are not set.
602   //
603   TGeoHMatrix ml;
604   if(!GetLocalMatrix(ml)) return kFALSE;
605   const Double_t *rot = ml.GetRotationMatrix();
606   return MatrixToAngles(rot,angles);
607 }
608
609 //_____________________________________________________________________________
610 Bool_t AliAlignObj::GetLocalMatrix(TGeoHMatrix& m) const
611 {
612   // Get the matrix for the local delta transformation.
613   // In case that the TGeo was not initialized or not closed,
614   // returns false and the object parameters are not set.
615   //
616   if (!gGeoManager || !gGeoManager->IsClosed()) {
617     AliError("Can't set the alignment object parameters! gGeoManager doesn't exist or it is still opened!");
618     return kFALSE;
619   }
620
621   const char* symname = GetSymName();
622   TGeoPhysicalNode* node;
623   TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
624   if(pne){
625     node = gGeoManager->MakeAlignablePN(pne);
626   }else{
627     AliWarning(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as volume path!",symname));
628     node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(symname);
629   }
630
631   if (!node) {
632     AliError(Form("Volume name or path %s not valid!",symname));
633     return kFALSE;
634   }
635   if (node->IsAligned())
636     AliWarning(Form("Volume %s has been already misaligned!",symname));
637
638   GetMatrix(m);
639   TGeoHMatrix gprime,gprimeinv;
640   gprime = *node->GetMatrix();
641   gprimeinv = gprime.Inverse();
642   m.Multiply(&gprime);
643   m.MultiplyLeft(&gprimeinv);
644
645   return kTRUE;
646 }
647
648 //_____________________________________________________________________________
649 Bool_t AliAlignObj::ApplyToGeometry()
650 {
651   // Apply the current alignment object to the TGeo geometry
652   // This method returns FALSE if the symname of the object was not
653   // valid neither to get a TGeoPEntry nor as a volume path
654   //
655   if (!gGeoManager || !gGeoManager->IsClosed()) {
656     AliError("Can't apply the alignment object! gGeoManager doesn't exist or it is still opened!");
657     return kFALSE;
658   }
659   
660   const char* symname = GetSymName();
661   const char* path;
662   TGeoPhysicalNode* node;
663   TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
664   if(pne){
665     path = pne->GetTitle();
666     if(!gGeoManager->CheckPath(path)){
667       AliDebug(1,Form("Valid PNEntry but invalid volume path %s!",path));
668           // this should happen only for volumes in disactivated branches
669       return kTRUE;
670     }
671     node = gGeoManager->MakeAlignablePN(pne);
672   }else{
673     AliWarning(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
674     path=symname;
675     if (!gGeoManager->CheckPath(path)) {
676       AliError(Form("Volume path %s not valid!",path));
677       return kFALSE;
678     }
679     if (gGeoManager->GetListOfPhysicalNodes()->FindObject(path)) {
680       AliError(Form("Volume %s has already been misaligned!",path));
681       return kFALSE;
682     }
683     node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(path);
684   }
685
686   if (!node) {
687     AliError(Form("Volume path %s not valid!",path));
688     return kFALSE;
689   }
690
691   TGeoHMatrix align,gprime;
692   gprime = *node->GetMatrix();
693   GetMatrix(align);
694   gprime.MultiplyLeft(&align);
695   TGeoHMatrix *ginv = new TGeoHMatrix;
696   TGeoHMatrix *g = node->GetMatrix(node->GetLevel()-1);
697   *ginv = g->Inverse();
698   *ginv *= gprime;
699   AliAlignObj::ELayerID layerId; // unique identity for layer in the alobj
700   Int_t modId; // unique identity for volume inside layer in the alobj
701   GetVolUID(layerId, modId);
702   AliDebug(2,Form("Aligning volume %s of detector layer %d with local ID %d",symname,layerId,modId));
703   node->Align(ginv);
704
705   return kTRUE;
706 }
707
708 //_____________________________________________________________________________
709 Bool_t AliAlignObj::GetFromGeometry(const char *symname, AliAlignObj &alobj)
710 {
711   // Get the alignment object which corresponds to the symbolic volume name
712   // symname (in case equal to the TGeo volume path)
713   // The method is extremely slow due to the searching by string.
714   // Therefore it should be used with great care!!
715   // This method returns FALSE if the symname of the object was not
716   // valid neither to get a TGeoPEntry nor as a volume path, or if the path
717   // associated to the TGeoPNEntry was not valid.
718   //
719
720   // Reset the alignment object
721   alobj.SetPars(0,0,0,0,0,0);
722   alobj.SetSymName(symname);
723
724   if (!gGeoManager || !gGeoManager->IsClosed()) {
725     AliErrorClass("Can't get the alignment object! gGeoManager doesn't exist or it is still opened!");
726     return kFALSE;
727   }
728
729   if (!gGeoManager->GetListOfPhysicalNodes()) {
730     AliErrorClass("Can't get the alignment object! gGeoManager doesn't contain any aligned nodes!");
731     return kFALSE;
732   }
733
734   const char *path;
735   TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
736   if(pne){
737     path = pne->GetTitle();
738   }else{
739     AliWarningClass(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
740     path = symname;
741   }
742   TObjArray* nodesArr = gGeoManager->GetListOfPhysicalNodes();
743   TGeoPhysicalNode* node = NULL;
744   for (Int_t iNode = 0; iNode < nodesArr->GetEntriesFast(); iNode++) {
745     TGeoPhysicalNode* tempNode = (TGeoPhysicalNode*) nodesArr->UncheckedAt(iNode);
746     const char *nodePath = tempNode->GetName();
747     if (strcmp(symname,nodePath) == 0) {
748       node = tempNode;
749       break;
750     }
751   }
752
753   if (!node) {
754     if (!gGeoManager->cd(symname)) {
755       AliErrorClass(Form("%s not valid neither as symbolic volume name nor as volume path!",symname));
756       return kFALSE;
757     }
758     else {
759       AliWarningClass(Form("Volume (%s) has not been misaligned!",symname));
760       return kTRUE;
761     }
762   }
763
764   TGeoHMatrix align,gprime,g,ginv,l;
765   gprime = *node->GetMatrix();
766   l = *node->GetOriginalMatrix();
767   g = *node->GetMatrix(node->GetLevel()-1);
768   g *= l;
769   ginv = g.Inverse();
770   align = gprime * ginv;
771
772   return alobj.SetMatrix(align);
773 }
774
775 //_____________________________________________________________________________
776 void  AliAlignObj::InitAlignObjFromGeometry()
777 {
778   // Loop over all alignable volumes and extract
779   // the corresponding alignment objects from
780   // the TGeo geometry
781
782   if(fgAlignObjs[0]) return;
783   
784   InitSymNames();
785
786   for (Int_t iLayer = kFirstLayer; iLayer < AliAlignObj::kLastLayer; iLayer++) {
787     fgAlignObjs[iLayer-kFirstLayer] = new AliAlignObj*[AliAlignObj::LayerSize(iLayer)];
788     for (Int_t iModule = 0; iModule < AliAlignObj::LayerSize(iLayer); iModule++) {
789       UShort_t volid = AliAlignObj::LayerToVolUID(iLayer,iModule);
790       fgAlignObjs[iLayer-kFirstLayer][iModule] = new AliAlignObjAngles("",volid,0,0,0,0,0,0,kTRUE);
791       const char *symname = SymName(volid);
792       if (!GetFromGeometry(symname, *fgAlignObjs[iLayer-kFirstLayer][iModule]))
793         AliErrorClass(Form("Failed to extract the alignment object for the volume (ID=%d and path=%s) !",volid,symname));
794     }
795   }
796   
797 }
798
799 //_____________________________________________________________________________
800 AliAlignObj* AliAlignObj::GetAlignObj(UShort_t voluid) {
801   // Returns the alignment object for given volume ID
802   //
803   Int_t modId;
804   ELayerID layerId = VolUIDToLayer(voluid,modId);
805   return GetAlignObj(layerId,modId);
806 }
807
808 //_____________________________________________________________________________
809 AliAlignObj* AliAlignObj::GetAlignObj(ELayerID layerId, Int_t modId)
810 {
811   // Returns pointer to alignment object given its layer and module ID
812   //
813   if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
814     AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
815     return NULL;
816   }
817   InitAlignObjFromGeometry();
818
819   return fgAlignObjs[layerId-kFirstLayer][modId];
820 }
821
822 //_____________________________________________________________________________
823 const char* AliAlignObj::SymName(UShort_t voluid) {
824   // Returns the symbolic volume name for given volume ID
825   //
826   Int_t modId;
827   ELayerID layerId = VolUIDToLayer(voluid,modId);
828   return SymName(layerId,modId);
829 }
830
831 //_____________________________________________________________________________
832 const char* AliAlignObj::SymName(ELayerID layerId, Int_t modId)
833 {
834   // Returns the symbolic volume name given for a given layer
835   // and module ID
836   //
837   if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
838     AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
839     return NULL;
840   }
841   InitSymNames();
842
843   return fgVolPath[layerId-kFirstLayer][modId].Data();
844 }
845
846 //_____________________________________________________________________________
847 void AliAlignObj::InitSymNames()
848 {
849   // Initialize the LUTs which associate the symbolic volume names
850   // for each alignable volume with their unique numerical identity.
851   // The LUTs are static, so they are created during the instantiation
852   // of the first intance of AliAlignObj
853   //
854   if (fgVolPath[0]) return;
855
856   for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++)
857     fgVolPath[iLayer] = new TString[fgLayerSize[iLayer]];
858
859   TString symname;
860   Int_t modnum; // in the following, set it to 0 at the start of each layer
861
862   /*********************       ITS layers  ***********************/
863   TString strSPD = "ITS/SPD";
864   TString strSDD = "ITS/SDD";
865   TString strSSD = "ITS/SSD";
866   TString strStave = "/Stave";
867   TString strLadder = "/Ladder";
868   TString strSector = "/Sector";
869   TString strSensor = "/Sensor";
870   TString strEntryName1;
871   TString strEntryName2;
872
873   /*********************       SPD layer1  ***********************/
874   {
875     modnum = 0;
876
877     for(Int_t c1 = 1; c1<=10; c1++){
878       strEntryName1 = strSPD;
879       strEntryName1 += 0;
880       strEntryName1 += strSector;
881       strEntryName1 += (c1-1);
882       for(Int_t c2 =1; c2<=2; c2++){
883         strEntryName2 = strEntryName1;
884         strEntryName2 += strStave;
885         strEntryName2 += (c2-1);
886         for(Int_t c3 =1; c3<=4; c3++){
887           symname = strEntryName2;
888           symname += strLadder;
889           symname += (c3-1);
890           fgVolPath[kSPD1-kFirstLayer][modnum] = symname.Data();
891           modnum++;
892         }
893       }
894     }
895   }
896   
897   /*********************       SPD layer2  ***********************/
898   {
899     modnum = 0;
900
901     for(Int_t c1 = 1; c1<=10; c1++){
902       strEntryName1 = strSPD;
903       strEntryName1 += 1;
904       strEntryName1 += strSector;
905       strEntryName1 += (c1-1);
906       for(Int_t c2 =1; c2<=4; c2++){
907         strEntryName2 = strEntryName1;
908         strEntryName2 += strStave;
909         strEntryName2 += (c2-1);
910         for(Int_t c3 =1; c3<=4; c3++){
911           symname = strEntryName2;
912           symname += strLadder;
913           symname += (c3-1);
914           fgVolPath[kSPD2-kFirstLayer][modnum] = symname.Data();
915           modnum++;
916         }
917       }
918     }
919   }
920
921   /*********************       SDD layer1  ***********************/
922   {
923     modnum=0;
924
925     for(Int_t c1 = 1; c1<=14; c1++){
926       strEntryName1 = strSDD;
927       strEntryName1 += 2;
928       strEntryName1 +=strLadder;
929       strEntryName1 += (c1-1);
930       for(Int_t c2 =1; c2<=6; c2++){
931         symname = strEntryName1;
932         symname += strSensor;
933         symname += (c2-1);
934         fgVolPath[kSDD1-kFirstLayer][modnum] = symname.Data();
935         modnum++;
936       }
937     }
938   }
939
940   /*********************       SDD layer2  ***********************/
941   {
942     modnum=0;
943
944     for(Int_t c1 = 1; c1<=22; c1++){
945       strEntryName1 = strSDD;
946       strEntryName1 += 3;
947       strEntryName1 +=strLadder;
948       strEntryName1 += (c1-1);
949       for(Int_t c2 = 1; c2<=8; c2++){
950         symname = strEntryName1;
951         symname += strSensor;
952         symname += (c2-1);
953         fgVolPath[kSDD2-kFirstLayer][modnum] = symname.Data();
954         modnum++;
955       }
956     }
957   }
958
959   /*********************       SSD layer1  ***********************/
960   {
961     modnum=0;
962
963     for(Int_t c1 = 1; c1<=34; c1++){
964       strEntryName1 = strSSD;
965       strEntryName1 += 4;
966       strEntryName1 +=strLadder;
967       strEntryName1 += (c1-1);
968       for(Int_t c2 = 1; c2<=22; c2++){
969         symname = strEntryName1;
970         symname += strSensor;
971         symname += (c2-1);
972         fgVolPath[kSSD1-kFirstLayer][modnum] = symname.Data();
973         modnum++;
974       }
975     }
976   }
977
978   /*********************       SSD layer2  ***********************/
979   {
980     modnum=0;
981
982     for(Int_t c1 = 1; c1<=38; c1++){
983       strEntryName1 = strSSD;
984       strEntryName1 += 5;
985       strEntryName1 +=strLadder;
986       strEntryName1 += (c1-1);
987       for(Int_t c2 = 1; c2<=25; c2++){
988         symname = strEntryName1;
989         symname += strSensor;
990         symname += (c2-1);
991         fgVolPath[kSSD2-kFirstLayer][modnum] = symname.Data();
992         modnum++;
993       }
994     }
995   }
996
997
998   /***************    TPC inner and outer layers    ****************/
999   TString sAsector="TPC/EndcapA/Sector";
1000   TString sCsector="TPC/EndcapC/Sector";
1001   TString sInner="/InnerChamber";
1002   TString sOuter="/OuterChamber";
1003   
1004   /***************    TPC inner chambers' layer    ****************/
1005   {
1006     modnum = 0;
1007     
1008     for(Int_t cnt=1; cnt<=18; cnt++){
1009       symname = sAsector;
1010       symname += cnt;
1011       symname += sInner;
1012       fgVolPath[kTPC1-kFirstLayer][modnum] = symname.Data();
1013       modnum++;
1014     }
1015     for(Int_t cnt=1; cnt<=18; cnt++){
1016       symname = sCsector;
1017       symname += cnt;
1018       symname += sInner;
1019       fgVolPath[kTPC1-kFirstLayer][modnum] = symname.Data();
1020       modnum++;
1021     }
1022   }
1023
1024   /***************    TPC outer chambers' layer    ****************/
1025   {
1026     modnum = 0;
1027     
1028     for(Int_t cnt=1; cnt<=18; cnt++){
1029       symname = sAsector;
1030       symname += cnt;
1031       symname += sOuter;
1032       fgVolPath[kTPC2-kFirstLayer][modnum] = symname.Data();
1033       modnum++;
1034     }
1035     for(Int_t cnt=1; cnt<=18; cnt++){
1036       symname = sCsector;
1037       symname += cnt;
1038       symname += sOuter;
1039       fgVolPath[kTPC2-kFirstLayer][modnum] = symname.Data();
1040       modnum++;
1041     }
1042   }    
1043
1044   /*********************       TOF layer   ***********************/
1045   {
1046     modnum=0;
1047     
1048     Int_t nstrA=15;
1049     Int_t nstrB=19;
1050     Int_t nstrC=19;
1051     Int_t nSectors=18;
1052     Int_t nStrips=nstrA+2*nstrB+2*nstrC;
1053     
1054     TString snSM  = "TOF/sm";
1055     TString snSTRIP = "/strip";
1056     
1057     for (Int_t isect = 0; isect < nSectors; isect++) {
1058       for (Int_t istr = 1; istr <= nStrips; istr++) {   
1059         symname  = snSM;
1060         symname += Form("%02d",isect);
1061         symname += snSTRIP;
1062         symname += Form("%02d",istr);
1063         fgVolPath[kTOF-kFirstLayer][modnum] = symname.Data();   
1064         modnum++;
1065       }
1066     }
1067   } 
1068
1069   /*********************      HMPID layer   ***********************/
1070   {
1071     TString str = "/HMPID/Chamber";
1072     TString symname;
1073
1074     for (modnum=0; modnum < 7; modnum++) {
1075       symname = str;
1076       symname += modnum;
1077       fgVolPath[kHMPID-kFirstLayer][modnum] = symname.Data();
1078     }
1079   }
1080
1081   /*********************      TRD layers 1-6   *******************/
1082   //!! 6 layers with index increasing in outwards direction
1083   {
1084     Int_t arTRDlayId[6] = {kTRD1, kTRD2, kTRD3, kTRD4, kTRD5, kTRD6};
1085
1086     TString snStr  = "TRD/sm";
1087     TString snApp1 = "/st";
1088     TString snApp2 = "/pl";
1089     
1090     for(Int_t layer=0; layer<6; layer++){
1091       modnum=0;
1092       for (Int_t isect = 0; isect < 18; isect++) {
1093         for (Int_t icham = 0; icham < 5; icham++) {
1094           symname  = snStr;
1095           symname += Form("%02d",isect);
1096           symname += snApp1;
1097           symname += icham;
1098           symname += snApp2;
1099           symname += layer;
1100           fgVolPath[arTRDlayId[layer]-kFirstLayer][modnum] = symname.Data();
1101           modnum++;
1102         }
1103       }
1104     }
1105   }
1106 }
1107