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