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 if(!gGeoManager->CheckPath(path)){
667 AliDebug(1,Form("Valid PNEntry but invalid volume path %s!",path));
668 // this should happen only for volumes in disactivated branches
671 node = gGeoManager->MakeAlignablePN(pne);
673 AliWarning(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
675 if (!gGeoManager->CheckPath(path)) {
676 AliError(Form("Volume path %s not valid!",path));
679 if (gGeoManager->GetListOfPhysicalNodes()->FindObject(path)) {
680 AliError(Form("Volume %s has already been misaligned!",path));
683 node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(path);
687 AliError(Form("Volume path %s not valid!",path));
691 TGeoHMatrix align,gprime;
692 gprime = *node->GetMatrix();
694 gprime.MultiplyLeft(&align);
695 TGeoHMatrix *ginv = new TGeoHMatrix;
696 TGeoHMatrix *g = node->GetMatrix(node->GetLevel()-1);
697 *ginv = g->Inverse();
699 AliAlignObj::ELayerID layerId; // unique identity for layer in the alobj
700 Int_t modId; // unique identity for volume inside layer in the alobj
701 GetVolUID(layerId, modId);
702 AliDebug(2,Form("Aligning volume %s of detector layer %d with local ID %d",symname,layerId,modId));
708 //_____________________________________________________________________________
709 Bool_t AliAlignObj::GetFromGeometry(const char *symname, AliAlignObj &alobj)
711 // Get the alignment object which corresponds to the symbolic volume name
712 // symname (in case equal to the TGeo volume path)
713 // The method is extremely slow due to the searching by string.
714 // Therefore it should be used with great care!!
715 // This method returns FALSE if the symname of the object was not
716 // valid neither to get a TGeoPEntry nor as a volume path, or if the path
717 // associated to the TGeoPNEntry was not valid.
720 // Reset the alignment object
721 alobj.SetPars(0,0,0,0,0,0);
722 alobj.SetSymName(symname);
724 if (!gGeoManager || !gGeoManager->IsClosed()) {
725 AliErrorClass("Can't get the alignment object! gGeoManager doesn't exist or it is still opened!");
729 if (!gGeoManager->GetListOfPhysicalNodes()) {
730 AliErrorClass("Can't get the alignment object! gGeoManager doesn't contain any aligned nodes!");
735 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
737 path = pne->GetTitle();
739 AliWarningClass(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
742 TObjArray* nodesArr = gGeoManager->GetListOfPhysicalNodes();
743 TGeoPhysicalNode* node = NULL;
744 for (Int_t iNode = 0; iNode < nodesArr->GetEntriesFast(); iNode++) {
745 TGeoPhysicalNode* tempNode = (TGeoPhysicalNode*) nodesArr->UncheckedAt(iNode);
746 const char *nodePath = tempNode->GetName();
747 if (strcmp(symname,nodePath) == 0) {
754 if (!gGeoManager->cd(symname)) {
755 AliErrorClass(Form("%s not valid neither as symbolic volume name nor as volume path!",symname));
759 AliWarningClass(Form("Volume (%s) has not been misaligned!",symname));
764 TGeoHMatrix align,gprime,g,ginv,l;
765 gprime = *node->GetMatrix();
766 l = *node->GetOriginalMatrix();
767 g = *node->GetMatrix(node->GetLevel()-1);
770 align = gprime * ginv;
772 return alobj.SetMatrix(align);
775 //_____________________________________________________________________________
776 void AliAlignObj::InitAlignObjFromGeometry()
778 // Loop over all alignable volumes and extract
779 // the corresponding alignment objects from
782 if(fgAlignObjs[0]) return;
786 for (Int_t iLayer = kFirstLayer; iLayer < AliAlignObj::kLastLayer; iLayer++) {
787 fgAlignObjs[iLayer-kFirstLayer] = new AliAlignObj*[AliAlignObj::LayerSize(iLayer)];
788 for (Int_t iModule = 0; iModule < AliAlignObj::LayerSize(iLayer); iModule++) {
789 UShort_t volid = AliAlignObj::LayerToVolUID(iLayer,iModule);
790 fgAlignObjs[iLayer-kFirstLayer][iModule] = new AliAlignObjAngles("",volid,0,0,0,0,0,0,kTRUE);
791 const char *symname = SymName(volid);
792 if (!GetFromGeometry(symname, *fgAlignObjs[iLayer-kFirstLayer][iModule]))
793 AliErrorClass(Form("Failed to extract the alignment object for the volume (ID=%d and path=%s) !",volid,symname));
799 //_____________________________________________________________________________
800 AliAlignObj* AliAlignObj::GetAlignObj(UShort_t voluid) {
801 // Returns the alignment object for given volume ID
804 ELayerID layerId = VolUIDToLayer(voluid,modId);
805 return GetAlignObj(layerId,modId);
808 //_____________________________________________________________________________
809 AliAlignObj* AliAlignObj::GetAlignObj(ELayerID layerId, Int_t modId)
811 // Returns pointer to alignment object given its layer and module ID
813 if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
814 AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
817 InitAlignObjFromGeometry();
819 return fgAlignObjs[layerId-kFirstLayer][modId];
822 //_____________________________________________________________________________
823 const char* AliAlignObj::SymName(UShort_t voluid) {
824 // Returns the symbolic volume name for given volume ID
827 ELayerID layerId = VolUIDToLayer(voluid,modId);
828 return SymName(layerId,modId);
831 //_____________________________________________________________________________
832 const char* AliAlignObj::SymName(ELayerID layerId, Int_t modId)
834 // Returns the symbolic volume name given for a given layer
837 if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
838 AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
843 return fgVolPath[layerId-kFirstLayer][modId].Data();
846 //_____________________________________________________________________________
847 void AliAlignObj::InitSymNames()
849 // Initialize the LUTs which associate the symbolic volume names
850 // for each alignable volume with their unique numerical identity.
851 // The LUTs are static, so they are created during the instantiation
852 // of the first intance of AliAlignObj
854 if (fgVolPath[0]) return;
856 for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++)
857 fgVolPath[iLayer] = new TString[fgLayerSize[iLayer]];
860 Int_t modnum; // in the following, set it to 0 at the start of each layer
862 /********************* ITS layers ***********************/
863 TString strSPD = "ITS/SPD";
864 TString strSDD = "ITS/SDD";
865 TString strSSD = "ITS/SSD";
866 TString strStave = "/Stave";
867 TString strLadder = "/Ladder";
868 TString strSector = "/Sector";
869 TString strSensor = "/Sensor";
870 TString strEntryName1;
871 TString strEntryName2;
873 /********************* SPD layer1 ***********************/
877 for(Int_t c1 = 1; c1<=10; c1++){
878 strEntryName1 = strSPD;
880 strEntryName1 += strSector;
881 strEntryName1 += (c1-1);
882 for(Int_t c2 =1; c2<=2; c2++){
883 strEntryName2 = strEntryName1;
884 strEntryName2 += strStave;
885 strEntryName2 += (c2-1);
886 for(Int_t c3 =1; c3<=4; c3++){
887 symname = strEntryName2;
888 symname += strLadder;
890 fgVolPath[kSPD1-kFirstLayer][modnum] = symname.Data();
897 /********************* SPD layer2 ***********************/
901 for(Int_t c1 = 1; c1<=10; c1++){
902 strEntryName1 = strSPD;
904 strEntryName1 += strSector;
905 strEntryName1 += (c1-1);
906 for(Int_t c2 =1; c2<=4; c2++){
907 strEntryName2 = strEntryName1;
908 strEntryName2 += strStave;
909 strEntryName2 += (c2-1);
910 for(Int_t c3 =1; c3<=4; c3++){
911 symname = strEntryName2;
912 symname += strLadder;
914 fgVolPath[kSPD2-kFirstLayer][modnum] = symname.Data();
921 /********************* SDD layer1 ***********************/
925 for(Int_t c1 = 1; c1<=14; c1++){
926 strEntryName1 = strSDD;
928 strEntryName1 +=strLadder;
929 strEntryName1 += (c1-1);
930 for(Int_t c2 =1; c2<=6; c2++){
931 symname = strEntryName1;
932 symname += strSensor;
934 fgVolPath[kSDD1-kFirstLayer][modnum] = symname.Data();
940 /********************* SDD layer2 ***********************/
944 for(Int_t c1 = 1; c1<=22; c1++){
945 strEntryName1 = strSDD;
947 strEntryName1 +=strLadder;
948 strEntryName1 += (c1-1);
949 for(Int_t c2 = 1; c2<=8; c2++){
950 symname = strEntryName1;
951 symname += strSensor;
953 fgVolPath[kSDD2-kFirstLayer][modnum] = symname.Data();
959 /********************* SSD layer1 ***********************/
963 for(Int_t c1 = 1; c1<=34; c1++){
964 strEntryName1 = strSSD;
966 strEntryName1 +=strLadder;
967 strEntryName1 += (c1-1);
968 for(Int_t c2 = 1; c2<=22; c2++){
969 symname = strEntryName1;
970 symname += strSensor;
972 fgVolPath[kSSD1-kFirstLayer][modnum] = symname.Data();
978 /********************* SSD layer2 ***********************/
982 for(Int_t c1 = 1; c1<=38; c1++){
983 strEntryName1 = strSSD;
985 strEntryName1 +=strLadder;
986 strEntryName1 += (c1-1);
987 for(Int_t c2 = 1; c2<=25; c2++){
988 symname = strEntryName1;
989 symname += strSensor;
991 fgVolPath[kSSD2-kFirstLayer][modnum] = symname.Data();
998 /*************** TPC inner and outer layers ****************/
999 TString sAsector="TPC/EndcapA/Sector";
1000 TString sCsector="TPC/EndcapC/Sector";
1001 TString sInner="/InnerChamber";
1002 TString sOuter="/OuterChamber";
1004 /*************** TPC inner chambers' layer ****************/
1008 for(Int_t cnt=1; cnt<=18; cnt++){
1012 fgVolPath[kTPC1-kFirstLayer][modnum] = symname.Data();
1015 for(Int_t cnt=1; cnt<=18; cnt++){
1019 fgVolPath[kTPC1-kFirstLayer][modnum] = symname.Data();
1024 /*************** TPC outer chambers' layer ****************/
1028 for(Int_t cnt=1; cnt<=18; cnt++){
1032 fgVolPath[kTPC2-kFirstLayer][modnum] = symname.Data();
1035 for(Int_t cnt=1; cnt<=18; cnt++){
1039 fgVolPath[kTPC2-kFirstLayer][modnum] = symname.Data();
1044 /********************* TOF layer ***********************/
1052 Int_t nStrips=nstrA+2*nstrB+2*nstrC;
1054 TString snSM = "TOF/sm";
1055 TString snSTRIP = "/strip";
1057 for (Int_t isect = 0; isect < nSectors; isect++) {
1058 for (Int_t istr = 1; istr <= nStrips; istr++) {
1060 symname += Form("%02d",isect);
1062 symname += Form("%02d",istr);
1063 fgVolPath[kTOF-kFirstLayer][modnum] = symname.Data();
1069 /********************* HMPID layer ***********************/
1071 TString str = "/HMPID/Chamber";
1074 for (modnum=0; modnum < 7; modnum++) {
1077 fgVolPath[kHMPID-kFirstLayer][modnum] = symname.Data();
1081 /********************* TRD layers 1-6 *******************/
1082 //!! 6 layers with index increasing in outwards direction
1084 Int_t arTRDlayId[6] = {kTRD1, kTRD2, kTRD3, kTRD4, kTRD5, kTRD6};
1086 TString snStr = "TRD/sm";
1087 TString snApp1 = "/st";
1088 TString snApp2 = "/pl";
1090 for(Int_t layer=0; layer<6; layer++){
1092 for (Int_t isect = 0; isect < 18; isect++) {
1093 for (Int_t icham = 0; icham < 5; icham++) {
1095 symname += Form("%02d",isect);
1100 fgVolPath[arTRDlayId[layer]-kFirstLayer][modnum] = symname.Data();