]> git.uio.no Git - u/mrichter/AliRoot.git/blob - STEER/AliAlignObj.cxx
Removing dead code (Raffaele)
[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     node = gGeoManager->MakeAlignablePN(pne);
667   }else{
668     AliWarning(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
669     path=symname;
670     if (!gGeoManager->CheckPath(path)) {
671       AliError(Form("Volume path %s not valid!",path));
672       return kFALSE;
673     }
674     if (gGeoManager->GetListOfPhysicalNodes()->FindObject(path)) {
675       AliError(Form("Volume %s has already been misaligned!",path));
676       return kFALSE;
677     }
678     node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(path);
679   }
680
681   if (!node) {
682     AliError(Form("Volume path %s not valid!",path));
683     return kFALSE;
684   }
685
686   TGeoHMatrix align,gprime;
687   gprime = *node->GetMatrix();
688   GetMatrix(align);
689   gprime.MultiplyLeft(&align);
690   TGeoHMatrix *ginv = new TGeoHMatrix;
691   TGeoHMatrix *g = node->GetMatrix(node->GetLevel()-1);
692   *ginv = g->Inverse();
693   *ginv *= gprime;
694   AliAlignObj::ELayerID layerId; // unique identity for layer in the alobj
695   Int_t modId; // unique identity for volume inside layer in the alobj
696   GetVolUID(layerId, modId);
697   AliDebug(2,Form("Aligning volume %s of detector layer %d with local ID %d",symname,layerId,modId));
698   node->Align(ginv);
699
700   return kTRUE;
701 }
702
703 //_____________________________________________________________________________
704 Bool_t AliAlignObj::GetFromGeometry(const char *symname, AliAlignObj &alobj)
705 {
706   // Get the alignment object which corresponds to the symbolic volume name
707   // symname (in case equal to the TGeo volume path)
708   // The method is extremely slow due to the searching by string.
709   // Therefore it should be used with great care!!
710   // This method returns FALSE if the symname of the object was not
711   // valid neither to get a TGeoPEntry nor as a volume path, or if the path
712   // associated to the TGeoPNEntry was not valid.
713   //
714
715   // Reset the alignment object
716   alobj.SetPars(0,0,0,0,0,0);
717   alobj.SetSymName(symname);
718
719   if (!gGeoManager || !gGeoManager->IsClosed()) {
720     AliErrorClass("Can't get the alignment object! gGeoManager doesn't exist or it is still opened!");
721     return kFALSE;
722   }
723
724   if (!gGeoManager->GetListOfPhysicalNodes()) {
725     AliErrorClass("Can't get the alignment object! gGeoManager doesn't contain any aligned nodes!");
726     return kFALSE;
727   }
728
729   const char *path;
730   TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
731   if(pne){
732     path = pne->GetTitle();
733   }else{
734     AliWarningClass(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
735     path = symname;
736   }
737   TObjArray* nodesArr = gGeoManager->GetListOfPhysicalNodes();
738   TGeoPhysicalNode* node = NULL;
739   for (Int_t iNode = 0; iNode < nodesArr->GetEntriesFast(); iNode++) {
740     TGeoPhysicalNode* tempNode = (TGeoPhysicalNode*) nodesArr->UncheckedAt(iNode);
741     const char *nodePath = tempNode->GetName();
742     if (strcmp(symname,nodePath) == 0) {
743       node = tempNode;
744       break;
745     }
746   }
747
748   if (!node) {
749     if (!gGeoManager->cd(symname)) {
750       AliErrorClass(Form("%s not valid neither as symbolic volume name nor as volume path!",symname));
751       return kFALSE;
752     }
753     else {
754       AliWarningClass(Form("Volume (%s) has not been misaligned!",symname));
755       return kTRUE;
756     }
757   }
758
759   TGeoHMatrix align,gprime,g,ginv,l;
760   gprime = *node->GetMatrix();
761   l = *node->GetOriginalMatrix();
762   g = *node->GetMatrix(node->GetLevel()-1);
763   g *= l;
764   ginv = g.Inverse();
765   align = gprime * ginv;
766
767   return alobj.SetMatrix(align);
768 }
769
770 //_____________________________________________________________________________
771 void  AliAlignObj::InitAlignObjFromGeometry()
772 {
773   // Loop over all alignable volumes and extract
774   // the corresponding alignment objects from
775   // the TGeo geometry
776
777   if(fgAlignObjs[0]) return;
778   
779   InitSymNames();
780
781   for (Int_t iLayer = kFirstLayer; iLayer < AliAlignObj::kLastLayer; iLayer++) {
782     fgAlignObjs[iLayer-kFirstLayer] = new AliAlignObj*[AliAlignObj::LayerSize(iLayer)];
783     for (Int_t iModule = 0; iModule < AliAlignObj::LayerSize(iLayer); iModule++) {
784       UShort_t volid = AliAlignObj::LayerToVolUID(iLayer,iModule);
785       fgAlignObjs[iLayer-kFirstLayer][iModule] = new AliAlignObjAngles("",volid,0,0,0,0,0,0,kTRUE);
786       const char *symname = SymName(volid);
787       if (!GetFromGeometry(symname, *fgAlignObjs[iLayer-kFirstLayer][iModule]))
788         AliErrorClass(Form("Failed to extract the alignment object for the volume (ID=%d and path=%s) !",volid,symname));
789     }
790   }
791   
792 }
793
794 //_____________________________________________________________________________
795 AliAlignObj* AliAlignObj::GetAlignObj(UShort_t voluid) {
796   // Returns the alignment object for given volume ID
797   //
798   Int_t modId;
799   ELayerID layerId = VolUIDToLayer(voluid,modId);
800   return GetAlignObj(layerId,modId);
801 }
802
803 //_____________________________________________________________________________
804 AliAlignObj* AliAlignObj::GetAlignObj(ELayerID layerId, Int_t modId)
805 {
806   // Returns pointer to alignment object given its layer and module ID
807   //
808   if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
809     AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
810     return NULL;
811   }
812   InitAlignObjFromGeometry();
813
814   return fgAlignObjs[layerId-kFirstLayer][modId];
815 }
816
817 //_____________________________________________________________________________
818 const char* AliAlignObj::SymName(UShort_t voluid) {
819   // Returns the symbolic volume name for given volume ID
820   //
821   Int_t modId;
822   ELayerID layerId = VolUIDToLayer(voluid,modId);
823   return SymName(layerId,modId);
824 }
825
826 //_____________________________________________________________________________
827 const char* AliAlignObj::SymName(ELayerID layerId, Int_t modId)
828 {
829   // Returns the symbolic volume name given for a given layer
830   // and module ID
831   //
832   if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
833     AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
834     return NULL;
835   }
836   InitSymNames();
837
838   return fgVolPath[layerId-kFirstLayer][modId].Data();
839 }
840
841 //_____________________________________________________________________________
842 void AliAlignObj::InitSymNames()
843 {
844   // Initialize the LUTs which associate the symbolic volume names
845   // for each alignable volume with their unique numerical identity.
846   // The LUTs are static, so they are created during the instantiation
847   // of the first intance of AliAlignObj
848   //
849   if (fgVolPath[0]) return;
850
851   for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++)
852     fgVolPath[iLayer] = new TString[fgLayerSize[iLayer]];
853
854   TString symname;
855   Int_t modnum; // in the following, set it to 0 at the start of each layer
856
857   /*********************       ITS layers  ***********************/
858   TString strSPD = "ITS/SPD";
859   TString strSDD = "ITS/SDD";
860   TString strSSD = "ITS/SSD";
861   TString strStave = "/Stave";
862   TString strLadder = "/Ladder";
863   TString strSector = "/Sector";
864   TString strSensor = "/Sensor";
865   TString strEntryName1;
866   TString strEntryName2;
867
868   /*********************       SPD layer1  ***********************/
869   {
870     modnum = 0;
871
872     for(Int_t c1 = 1; c1<=10; c1++){
873       strEntryName1 = strSPD;
874       strEntryName1 += 0;
875       strEntryName1 += strSector;
876       strEntryName1 += (c1-1);
877       for(Int_t c2 =1; c2<=2; c2++){
878         strEntryName2 = strEntryName1;
879         strEntryName2 += strStave;
880         strEntryName2 += (c2-1);
881         for(Int_t c3 =1; c3<=4; c3++){
882           symname = strEntryName2;
883           symname += strLadder;
884           symname += (c3-1);
885           fgVolPath[kSPD1-kFirstLayer][modnum] = symname.Data();
886           modnum++;
887         }
888       }
889     }
890   }
891   
892   /*********************       SPD layer2  ***********************/
893   {
894     modnum = 0;
895
896     for(Int_t c1 = 1; c1<=10; c1++){
897       strEntryName1 = strSPD;
898       strEntryName1 += 1;
899       strEntryName1 += strSector;
900       strEntryName1 += (c1-1);
901       for(Int_t c2 =1; c2<=4; c2++){
902         strEntryName2 = strEntryName1;
903         strEntryName2 += strStave;
904         strEntryName2 += (c2-1);
905         for(Int_t c3 =1; c3<=4; c3++){
906           symname = strEntryName2;
907           symname += strLadder;
908           symname += (c3-1);
909           fgVolPath[kSPD2-kFirstLayer][modnum] = symname.Data();
910           modnum++;
911         }
912       }
913     }
914   }
915
916   /*********************       SDD layer1  ***********************/
917   {
918     modnum=0;
919
920     for(Int_t c1 = 1; c1<=14; c1++){
921       strEntryName1 = strSDD;
922       strEntryName1 += 2;
923       strEntryName1 +=strLadder;
924       strEntryName1 += (c1-1);
925       for(Int_t c2 =1; c2<=6; c2++){
926         symname = strEntryName1;
927         symname += strSensor;
928         symname += (c2-1);
929         fgVolPath[kSDD1-kFirstLayer][modnum] = symname.Data();
930         modnum++;
931       }
932     }
933   }
934
935   /*********************       SDD layer2  ***********************/
936   {
937     modnum=0;
938
939     for(Int_t c1 = 1; c1<=22; c1++){
940       strEntryName1 = strSDD;
941       strEntryName1 += 3;
942       strEntryName1 +=strLadder;
943       strEntryName1 += (c1-1);
944       for(Int_t c2 = 1; c2<=8; c2++){
945         symname = strEntryName1;
946         symname += strSensor;
947         symname += (c2-1);
948         fgVolPath[kSDD2-kFirstLayer][modnum] = symname.Data();
949         modnum++;
950       }
951     }
952   }
953
954   /*********************       SSD layer1  ***********************/
955   {
956     modnum=0;
957
958     for(Int_t c1 = 1; c1<=34; c1++){
959       strEntryName1 = strSSD;
960       strEntryName1 += 4;
961       strEntryName1 +=strLadder;
962       strEntryName1 += (c1-1);
963       for(Int_t c2 = 1; c2<=22; c2++){
964         symname = strEntryName1;
965         symname += strSensor;
966         symname += (c2-1);
967         fgVolPath[kSSD1-kFirstLayer][modnum] = symname.Data();
968         modnum++;
969       }
970     }
971   }
972
973   /*********************       SSD layer2  ***********************/
974   {
975     modnum=0;
976
977     for(Int_t c1 = 1; c1<=38; c1++){
978       strEntryName1 = strSSD;
979       strEntryName1 += 5;
980       strEntryName1 +=strLadder;
981       strEntryName1 += (c1-1);
982       for(Int_t c2 = 1; c2<=25; c2++){
983         symname = strEntryName1;
984         symname += strSensor;
985         symname += (c2-1);
986         fgVolPath[kSSD2-kFirstLayer][modnum] = symname.Data();
987         modnum++;
988       }
989     }
990   }
991
992
993   /***************    TPC inner and outer layers    ****************/
994   TString sAsector="TPC/EndcapA/Sector";
995   TString sCsector="TPC/EndcapC/Sector";
996   TString sInner="/InnerChamber";
997   TString sOuter="/OuterChamber";
998   
999   /***************    TPC inner chambers' layer    ****************/
1000   {
1001     modnum = 0;
1002     
1003     for(Int_t cnt=1; cnt<=18; cnt++){
1004       symname = sAsector;
1005       symname += cnt;
1006       symname += sInner;
1007       fgVolPath[kTPC1-kFirstLayer][modnum] = symname.Data();
1008       modnum++;
1009     }
1010     for(Int_t cnt=1; cnt<=18; cnt++){
1011       symname = sCsector;
1012       symname += cnt;
1013       symname += sInner;
1014       fgVolPath[kTPC1-kFirstLayer][modnum] = symname.Data();
1015       modnum++;
1016     }
1017   }
1018
1019   /***************    TPC outer chambers' layer    ****************/
1020   {
1021     modnum = 0;
1022     
1023     for(Int_t cnt=1; cnt<=18; cnt++){
1024       symname = sAsector;
1025       symname += cnt;
1026       symname += sOuter;
1027       fgVolPath[kTPC2-kFirstLayer][modnum] = symname.Data();
1028       modnum++;
1029     }
1030     for(Int_t cnt=1; cnt<=18; cnt++){
1031       symname = sCsector;
1032       symname += cnt;
1033       symname += sOuter;
1034       fgVolPath[kTPC2-kFirstLayer][modnum] = symname.Data();
1035       modnum++;
1036     }
1037   }    
1038
1039   /*********************       TOF layer   ***********************/
1040   {
1041     modnum=0;
1042     
1043     Int_t nstrA=15;
1044     Int_t nstrB=19;
1045     Int_t nstrC=19;
1046     Int_t nSectors=18;
1047     Int_t nStrips=nstrA+2*nstrB+2*nstrC;
1048     
1049     TString snSM  = "TOF/sm";
1050     TString snSTRIP = "/strip";
1051     
1052     for (Int_t isect = 0; isect < nSectors; isect++) {
1053       for (Int_t istr = 1; istr <= nStrips; istr++) {   
1054         symname  = snSM;
1055         symname += Form("%02d",isect);
1056         symname += snSTRIP;
1057         symname += Form("%02d",istr);
1058         fgVolPath[kTOF-kFirstLayer][modnum] = symname.Data();   
1059         modnum++;
1060       }
1061     }
1062   } 
1063
1064   /*********************      HMPID layer   ***********************/
1065   {
1066     TString str = "/HMPID/Chamber";
1067     TString symname;
1068
1069     for (modnum=0; modnum < 7; modnum++) {
1070       symname = str;
1071       symname += modnum;
1072       fgVolPath[kHMPID-kFirstLayer][modnum] = symname.Data();
1073     }
1074   }
1075
1076   /*********************      TRD layers 1-6   *******************/
1077   //!! 6 layers with index increasing in outwards direction
1078   {
1079     Int_t arTRDlayId[6] = {kTRD1, kTRD2, kTRD3, kTRD4, kTRD5, kTRD6};
1080
1081     TString snStr  = "TRD/sm";
1082     TString snApp1 = "/st";
1083     TString snApp2 = "/pl";
1084     
1085     for(Int_t layer=0; layer<6; layer++){
1086       modnum=0;
1087       for (Int_t isect = 0; isect < 18; isect++) {
1088         for (Int_t icham = 0; icham < 5; icham++) {
1089           symname  = snStr;
1090           symname += Form("%02d",isect);
1091           symname += snApp1;
1092           symname += icham;
1093           symname += snApp2;
1094           symname += layer;
1095           fgVolPath[arTRDlayId[layer]-kFirstLayer][modnum] = symname.Data();
1096           modnum++;
1097         }
1098       }
1099     }
1100   }
1101 }
1102