1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
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>
28 #include "AliAlignObj.h"
29 #include "AliTrackPointArray.h"
31 #include "AliAlignObjAngles.h"
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
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",
60 TString* AliAlignObj::fgVolPath[kLastLayer - kFirstLayer] = {
73 AliAlignObj** AliAlignObj::fgAlignObjs[kLastLayer - kFirstLayer] = {
86 //_____________________________________________________________________________
87 AliAlignObj::AliAlignObj():
91 // default constructor
95 //_____________________________________________________________________________
96 AliAlignObj::AliAlignObj(const char* symname, UShort_t voluid) :
101 // standard constructor
105 //_____________________________________________________________________________
106 AliAlignObj::AliAlignObj(const AliAlignObj& theAlignObj) :
107 TObject(theAlignObj),
108 fVolPath(theAlignObj.GetSymName()),
109 fVolUID(theAlignObj.GetVolUID())
114 //_____________________________________________________________________________
115 AliAlignObj &AliAlignObj::operator =(const AliAlignObj& theAlignObj)
117 // assignment operator
118 if(this==&theAlignObj) return *this;
119 fVolPath = theAlignObj.GetSymName();
120 fVolUID = theAlignObj.GetVolUID();
124 //_____________________________________________________________________________
125 AliAlignObj &AliAlignObj::operator*=(const AliAlignObj& theAlignObj)
127 // multiplication operator
128 // The operator can be used to 'combine'
129 // two alignment objects
133 theAlignObj.GetMatrix(m2);
134 m1.MultiplyLeft(&m2);
139 //_____________________________________________________________________________
140 AliAlignObj::~AliAlignObj()
145 //_____________________________________________________________________________
146 void AliAlignObj::SetVolUID(ELayerID detId, Int_t modId)
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).
153 fVolUID = LayerToVolUID(detId,modId);
156 //_____________________________________________________________________________
157 void AliAlignObj::GetVolUID(ELayerID &layerId, Int_t &modId) const
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.
166 layerId = VolUIDToLayer(fVolUID,modId);
169 //_____________________________________________________________________________
170 Bool_t AliAlignObj::GetPars(Double_t tr[], Double_t angles[]) const
173 return GetAngles(angles);
176 //_____________________________________________________________________________
177 Int_t AliAlignObj::GetLevel() const
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
184 AliWarning("gGeoManager doesn't exist or it is still opened: unable to return meaningful level value.");
187 const char* symname = GetSymName();
189 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
191 path = pne->GetTitle();
196 TString path_str = path;
197 if(path_str[0]!='/') path_str.Prepend('/');
198 return path_str.CountChar('/');
201 //_____________________________________________________________________________
202 Int_t AliAlignObj::Compare(const TObject *obj) const
204 // Compare the levels of two
206 // Used in the sorting during
207 // the application of alignment
208 // objects to the geometry
210 Int_t level = GetLevel();
211 Int_t level2 = ((AliAlignObj *)obj)->GetLevel();
215 return ((level > level2) ? 1 : -1);
218 //_____________________________________________________________________________
219 void AliAlignObj::AnglesToMatrix(const Double_t *angles, Double_t *rot) const
221 // Calculates the rotation matrix using the
222 // Euler angles in "x y z" notation
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]);
232 rot[0] = costhe*cosphi;
233 rot[1] = -costhe*sinphi;
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;
243 //_____________________________________________________________________________
244 Bool_t AliAlignObj::MatrixToAngles(const Double_t *rot, Double_t *angles) const
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
251 if(TMath::Abs(rot[0])<1e-7 || TMath::Abs(rot[8])<1e-7) {
252 AliError("Failed to extract roll-pitch-yall angles!");
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]);
262 //______________________________________________________________________________
263 void AliAlignObj::Transform(AliTrackPoint &p) const
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
270 if (fVolUID != p.GetVolumeID())
271 AliWarning(Form("Alignment object ID is not equal to the space-point ID (%d != %d)",fVolUID,p.GetVolumeID()));
275 Double_t *rot = m.GetRotationMatrix();
276 Double_t *tr = m.GetTranslation();
278 Float_t xyzin[3],xyzout[3];
280 for (Int_t i = 0; i < 3; i++)
289 //_____________________________________________________________________________
290 void AliAlignObj::Transform(AliTrackPointArray &array) const
292 // This method is used to transform all the track points
293 // from the input AliTrackPointArray
296 for (Int_t i = 0; i < array.GetNPoints(); i++) {
299 array.AddPoint(i,&p);
303 //_____________________________________________________________________________
304 void AliAlignObj::Print(Option_t *) const
306 // Print the contents of the
307 // alignment object in angles and
308 // matrix representations
316 const Double_t *rot = m.GetRotationMatrix();
318 printf("Volume=%s\n",GetSymName());
319 if (GetVolUID() != 0) {
322 GetVolUID(layerId,modId);
323 printf("VolumeID=%d LayerID=%d ( %s ) ModuleID=%d\n", GetVolUID(),layerId,LayerName(layerId),modId);
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]);
331 //_____________________________________________________________________________
332 Int_t AliAlignObj::LayerSize(Int_t layerId)
334 // Get the layer size for layer corresponding to layerId.
335 // Implemented only for ITS,TPC,TRD,TOF and HMPID
337 if (layerId < kFirstLayer || layerId >= kLastLayer) {
338 AliErrorClass(Form("Invalid layer index %d ! Layer range is (%d -> %d) !",layerId,kFirstLayer,kLastLayer));
342 return fgLayerSize[layerId - kFirstLayer];
346 //_____________________________________________________________________________
347 const char* AliAlignObj::LayerName(Int_t layerId)
349 // Get the layer name corresponding to layerId.
350 // Implemented only for ITS,TPC,TRD,TOF and HMPID
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!";
357 return fgLayerName[layerId - kFirstLayer];
361 //_____________________________________________________________________________
362 UShort_t AliAlignObj::LayerToVolUID(ELayerID layerId, Int_t modId)
364 // From detector (layer) name and module number (according to detector
365 // internal numbering) build the unique numerical identity of that volume
367 // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
368 // remaining 11 for module ID inside det (2048 possible values).
370 return ((UShort_t(layerId) << 11) | UShort_t(modId));
373 //_____________________________________________________________________________
374 UShort_t AliAlignObj::LayerToVolUID(Int_t layerId, Int_t modId)
376 // From detector (layer) name and module number (according to detector
377 // internal numbering) build the unique numerical identity of that volume
379 // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
380 // remaining 11 for module ID inside det (2048 possible values).
382 return ((UShort_t(layerId) << 11) | UShort_t(modId));
385 //_____________________________________________________________________________
386 AliAlignObj::ELayerID AliAlignObj::VolUIDToLayer(UShort_t voluid, Int_t &modId)
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.
394 modId = voluid & 0x7ff;
396 return VolUIDToLayer(voluid);
399 //_____________________________________________________________________________
400 AliAlignObj::ELayerID AliAlignObj::VolUIDToLayer(UShort_t voluid)
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
407 return ELayerID((voluid >> 11) & 0x1f);
410 //_____________________________________________________________________________
411 void AliAlignObj::SetPars(Double_t x, Double_t y, Double_t z,
412 Double_t psi, Double_t theta, Double_t phi)
414 // Set the global delta transformation by passing 3 angles (expressed in
415 // degrees) and 3 shifts (in centimeters)
417 SetTranslation(x,y,z);
418 SetRotation(psi,theta,phi);
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)
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.
431 Double_t tr[3] = {x, y, z};
432 m.SetTranslation(tr);
433 Double_t angles[3] = {psi, theta, phi};
435 AnglesToMatrix(angles,rot);
438 return SetLocalMatrix(m);
442 //_____________________________________________________________________________
443 Bool_t AliAlignObj::SetLocalTranslation(Double_t x, Double_t y, Double_t z)
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.
452 Double_t tr[3] = {x, y, z};
453 m.SetTranslation(tr);
455 return SetLocalMatrix(m);
459 //_____________________________________________________________________________
460 Bool_t AliAlignObj::SetLocalTranslation(const TGeoMatrix& m)
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.
467 const Double_t* tr = m.GetTranslation();
469 mtr.SetTranslation(tr);
471 return SetLocalMatrix(mtr);
475 //_____________________________________________________________________________
476 Bool_t AliAlignObj::SetLocalRotation(Double_t psi, Double_t theta, Double_t phi)
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.
485 Double_t angles[3] = {psi, theta, phi};
487 AnglesToMatrix(angles,rot);
490 return SetLocalMatrix(m);
494 //_____________________________________________________________________________
495 Bool_t AliAlignObj::SetLocalRotation(const TGeoMatrix& m)
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.
503 const Double_t* rot = m.GetRotationMatrix();
504 rotm.SetRotation(rot);
506 return SetLocalMatrix(rotm);
510 //_____________________________________________________________________________
511 Bool_t AliAlignObj::SetLocalMatrix(const TGeoMatrix& m)
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.
518 if (!gGeoManager || !gGeoManager->IsClosed()) {
519 AliError("Can't set the alignment object parameters! gGeoManager doesn't exist or it is still opened!");
523 const char* symname = GetSymName();
524 TGeoPhysicalNode* node;
525 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
527 node = gGeoManager->MakeAlignablePN(pne);
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);
534 AliError(Form("Volume name or path %s not valid!",symname));
537 if (node->IsAligned())
538 AliWarning(Form("Volume %s has been already misaligned!",symname));
541 const Double_t *tr = m.GetTranslation();
542 m1.SetTranslation(tr);
543 const Double_t* rot = m.GetRotationMatrix();
546 TGeoHMatrix align,gprime,gprimeinv;
547 gprime = *node->GetMatrix();
548 gprimeinv = gprime.Inverse();
549 m1.Multiply(&gprimeinv);
550 m1.MultiplyLeft(&gprime);
552 return SetMatrix(m1);
555 //_____________________________________________________________________________
556 Bool_t AliAlignObj::SetMatrix(const TGeoMatrix& m)
558 // Set the global delta transformation by passing the TGeoMatrix
562 return SetRotation(m);
565 //_____________________________________________________________________________
566 Bool_t AliAlignObj::GetLocalPars(Double_t transl[], Double_t angles[]) const
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.
573 if(!GetLocalTranslation(transl)) return kFALSE;
574 return GetLocalAngles(angles);
577 //_____________________________________________________________________________
578 Bool_t AliAlignObj::GetLocalTranslation(Double_t* tr) const
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.
586 if(!GetLocalMatrix(ml)) return kFALSE;
587 const Double_t* transl;
588 transl = ml.GetTranslation();
595 //_____________________________________________________________________________
596 Bool_t AliAlignObj::GetLocalAngles(Double_t* angles) const
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.
604 if(!GetLocalMatrix(ml)) return kFALSE;
605 const Double_t *rot = ml.GetRotationMatrix();
606 return MatrixToAngles(rot,angles);
609 //_____________________________________________________________________________
610 Bool_t AliAlignObj::GetLocalMatrix(TGeoHMatrix& m) const
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.
616 if (!gGeoManager || !gGeoManager->IsClosed()) {
617 AliError("Can't set the alignment object parameters! gGeoManager doesn't exist or it is still opened!");
621 const char* symname = GetSymName();
622 TGeoPhysicalNode* node;
623 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
625 node = gGeoManager->MakeAlignablePN(pne);
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);
632 AliError(Form("Volume name or path %s not valid!",symname));
635 if (node->IsAligned())
636 AliWarning(Form("Volume %s has been already misaligned!",symname));
639 TGeoHMatrix gprime,gprimeinv;
640 gprime = *node->GetMatrix();
641 gprimeinv = gprime.Inverse();
643 m.MultiplyLeft(&gprimeinv);
648 //_____________________________________________________________________________
649 Bool_t AliAlignObj::ApplyToGeometry()
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
655 if (!gGeoManager || !gGeoManager->IsClosed()) {
656 AliError("Can't apply the alignment object! gGeoManager doesn't exist or it is still opened!");
660 const char* symname = GetSymName();
662 TGeoPhysicalNode* node;
663 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
665 path = pne->GetTitle();
666 node = gGeoManager->MakeAlignablePN(pne);
668 AliWarning(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
670 if (!gGeoManager->CheckPath(path)) {
671 AliError(Form("Volume path %s not valid!",path));
674 if (gGeoManager->GetListOfPhysicalNodes()->FindObject(path)) {
675 AliError(Form("Volume %s has already been misaligned!",path));
678 node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(path);
682 AliError(Form("Volume path %s not valid!",path));
686 TGeoHMatrix align,gprime;
687 gprime = *node->GetMatrix();
689 gprime.MultiplyLeft(&align);
690 TGeoHMatrix *ginv = new TGeoHMatrix;
691 TGeoHMatrix *g = node->GetMatrix(node->GetLevel()-1);
692 *ginv = g->Inverse();
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));
703 //_____________________________________________________________________________
704 Bool_t AliAlignObj::GetFromGeometry(const char *symname, AliAlignObj &alobj)
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.
715 // Reset the alignment object
716 alobj.SetPars(0,0,0,0,0,0);
717 alobj.SetSymName(symname);
719 if (!gGeoManager || !gGeoManager->IsClosed()) {
720 AliErrorClass("Can't get the alignment object! gGeoManager doesn't exist or it is still opened!");
724 if (!gGeoManager->GetListOfPhysicalNodes()) {
725 AliErrorClass("Can't get the alignment object! gGeoManager doesn't contain any aligned nodes!");
730 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
732 path = pne->GetTitle();
734 AliWarningClass(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
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) {
749 if (!gGeoManager->cd(symname)) {
750 AliErrorClass(Form("%s not valid neither as symbolic volume name nor as volume path!",symname));
754 AliWarningClass(Form("Volume (%s) has not been misaligned!",symname));
759 TGeoHMatrix align,gprime,g,ginv,l;
760 gprime = *node->GetMatrix();
761 l = *node->GetOriginalMatrix();
762 g = *node->GetMatrix(node->GetLevel()-1);
765 align = gprime * ginv;
767 return alobj.SetMatrix(align);
770 //_____________________________________________________________________________
771 void AliAlignObj::InitAlignObjFromGeometry()
773 // Loop over all alignable volumes and extract
774 // the corresponding alignment objects from
777 if(fgAlignObjs[0]) return;
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));
794 //_____________________________________________________________________________
795 AliAlignObj* AliAlignObj::GetAlignObj(UShort_t voluid) {
796 // Returns the alignment object for given volume ID
799 ELayerID layerId = VolUIDToLayer(voluid,modId);
800 return GetAlignObj(layerId,modId);
803 //_____________________________________________________________________________
804 AliAlignObj* AliAlignObj::GetAlignObj(ELayerID layerId, Int_t modId)
806 // Returns pointer to alignment object given its layer and module ID
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));
812 InitAlignObjFromGeometry();
814 return fgAlignObjs[layerId-kFirstLayer][modId];
817 //_____________________________________________________________________________
818 const char* AliAlignObj::SymName(UShort_t voluid) {
819 // Returns the symbolic volume name for given volume ID
822 ELayerID layerId = VolUIDToLayer(voluid,modId);
823 return SymName(layerId,modId);
826 //_____________________________________________________________________________
827 const char* AliAlignObj::SymName(ELayerID layerId, Int_t modId)
829 // Returns the symbolic volume name given for a given layer
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));
838 return fgVolPath[layerId-kFirstLayer][modId].Data();
841 //_____________________________________________________________________________
842 void AliAlignObj::InitSymNames()
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
849 if (fgVolPath[0]) return;
851 for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++)
852 fgVolPath[iLayer] = new TString[fgLayerSize[iLayer]];
855 Int_t modnum; // in the following, set it to 0 at the start of each layer
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;
868 /********************* SPD layer1 ***********************/
872 for(Int_t c1 = 1; c1<=10; c1++){
873 strEntryName1 = strSPD;
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;
885 fgVolPath[kSPD1-kFirstLayer][modnum] = symname.Data();
892 /********************* SPD layer2 ***********************/
896 for(Int_t c1 = 1; c1<=10; c1++){
897 strEntryName1 = strSPD;
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;
909 fgVolPath[kSPD2-kFirstLayer][modnum] = symname.Data();
916 /********************* SDD layer1 ***********************/
920 for(Int_t c1 = 1; c1<=14; c1++){
921 strEntryName1 = strSDD;
923 strEntryName1 +=strLadder;
924 strEntryName1 += (c1-1);
925 for(Int_t c2 =1; c2<=6; c2++){
926 symname = strEntryName1;
927 symname += strSensor;
929 fgVolPath[kSDD1-kFirstLayer][modnum] = symname.Data();
935 /********************* SDD layer2 ***********************/
939 for(Int_t c1 = 1; c1<=22; c1++){
940 strEntryName1 = strSDD;
942 strEntryName1 +=strLadder;
943 strEntryName1 += (c1-1);
944 for(Int_t c2 = 1; c2<=8; c2++){
945 symname = strEntryName1;
946 symname += strSensor;
948 fgVolPath[kSDD2-kFirstLayer][modnum] = symname.Data();
954 /********************* SSD layer1 ***********************/
958 for(Int_t c1 = 1; c1<=34; c1++){
959 strEntryName1 = strSSD;
961 strEntryName1 +=strLadder;
962 strEntryName1 += (c1-1);
963 for(Int_t c2 = 1; c2<=22; c2++){
964 symname = strEntryName1;
965 symname += strSensor;
967 fgVolPath[kSSD1-kFirstLayer][modnum] = symname.Data();
973 /********************* SSD layer2 ***********************/
977 for(Int_t c1 = 1; c1<=38; c1++){
978 strEntryName1 = strSSD;
980 strEntryName1 +=strLadder;
981 strEntryName1 += (c1-1);
982 for(Int_t c2 = 1; c2<=25; c2++){
983 symname = strEntryName1;
984 symname += strSensor;
986 fgVolPath[kSSD2-kFirstLayer][modnum] = symname.Data();
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";
999 /*************** TPC inner chambers' layer ****************/
1003 for(Int_t cnt=1; cnt<=18; cnt++){
1007 fgVolPath[kTPC1-kFirstLayer][modnum] = symname.Data();
1010 for(Int_t cnt=1; cnt<=18; cnt++){
1014 fgVolPath[kTPC1-kFirstLayer][modnum] = symname.Data();
1019 /*************** TPC outer chambers' layer ****************/
1023 for(Int_t cnt=1; cnt<=18; cnt++){
1027 fgVolPath[kTPC2-kFirstLayer][modnum] = symname.Data();
1030 for(Int_t cnt=1; cnt<=18; cnt++){
1034 fgVolPath[kTPC2-kFirstLayer][modnum] = symname.Data();
1039 /********************* TOF layer ***********************/
1047 Int_t nStrips=nstrA+2*nstrB+2*nstrC;
1049 TString snSM = "TOF/sm";
1050 TString snSTRIP = "/strip";
1052 for (Int_t isect = 0; isect < nSectors; isect++) {
1053 for (Int_t istr = 1; istr <= nStrips; istr++) {
1055 symname += Form("%02d",isect);
1057 symname += Form("%02d",istr);
1058 fgVolPath[kTOF-kFirstLayer][modnum] = symname.Data();
1064 /********************* HMPID layer ***********************/
1066 TString str = "/HMPID/Chamber";
1069 for (modnum=0; modnum < 7; modnum++) {
1072 fgVolPath[kHMPID-kFirstLayer][modnum] = symname.Data();
1076 /********************* TRD layers 1-6 *******************/
1077 //!! 6 layers with index increasing in outwards direction
1079 Int_t arTRDlayId[6] = {kTRD1, kTRD2, kTRD3, kTRD4, kTRD5, kTRD6};
1081 TString snStr = "TRD/sm";
1082 TString snApp1 = "/st";
1083 TString snApp2 = "/pl";
1085 for(Int_t layer=0; layer<6; layer++){
1087 for (Int_t isect = 0; isect < 18; isect++) {
1088 for (Int_t icham = 0; icham < 5; icham++) {
1090 symname += Form("%02d",isect);
1095 fgVolPath[arTRDlayId[layer]-kFirstLayer][modnum] = symname.Data();