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 //-----------------------------------------------------------------
26 #include <TGeoManager.h>
27 #include <TGeoPhysicalNode.h>
29 #include "TObjString.h"
31 #include "AliAlignObj.h"
32 #include "AliTrackPointArray.h"
34 #include "AliAlignObjAngles.h"
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
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",
63 TString* AliAlignObj::fgVolPath[kLastLayer - kFirstLayer] = {
76 AliAlignObj** AliAlignObj::fgAlignObjs[kLastLayer - kFirstLayer] = {
89 //_____________________________________________________________________________
90 AliAlignObj::AliAlignObj():
94 // default constructor
98 //_____________________________________________________________________________
99 AliAlignObj::AliAlignObj(const char* symname, UShort_t voluid) :
104 // standard constructor
108 //_____________________________________________________________________________
109 AliAlignObj::AliAlignObj(const AliAlignObj& theAlignObj) :
110 TObject(theAlignObj),
111 fVolPath(theAlignObj.GetSymName()),
112 fVolUID(theAlignObj.GetVolUID())
117 //_____________________________________________________________________________
118 AliAlignObj &AliAlignObj::operator =(const AliAlignObj& theAlignObj)
120 // assignment operator
121 if(this==&theAlignObj) return *this;
122 fVolPath = theAlignObj.GetSymName();
123 fVolUID = theAlignObj.GetVolUID();
127 //_____________________________________________________________________________
128 AliAlignObj &AliAlignObj::operator*=(const AliAlignObj& theAlignObj)
130 // multiplication operator
131 // The operator can be used to 'combine'
132 // two alignment objects
136 theAlignObj.GetMatrix(m2);
137 m1.MultiplyLeft(&m2);
142 //_____________________________________________________________________________
143 AliAlignObj::~AliAlignObj()
148 //_____________________________________________________________________________
149 void AliAlignObj::SetVolUID(ELayerID detId, Int_t modId)
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).
156 fVolUID = LayerToVolUID(detId,modId);
159 //_____________________________________________________________________________
160 void AliAlignObj::GetVolUID(ELayerID &layerId, Int_t &modId) const
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.
169 layerId = VolUIDToLayer(fVolUID,modId);
172 //_____________________________________________________________________________
173 Bool_t AliAlignObj::GetPars(Double_t tr[], Double_t angles[]) const
176 return GetAngles(angles);
179 //_____________________________________________________________________________
180 Int_t AliAlignObj::GetLevel() const
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
187 AliWarning("gGeoManager doesn't exist or it is still opened: unable to return meaningful level value.");
190 const char* symname = GetSymName();
192 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
194 path = pne->GetTitle();
199 TString path_str = path;
200 if(path_str[0]!='/') path_str.Prepend('/');
201 return path_str.CountChar('/');
204 //_____________________________________________________________________________
205 Int_t AliAlignObj::Compare(const TObject *obj) const
207 // Compare the levels of two
209 // Used in the sorting during
210 // the application of alignment
211 // objects to the geometry
213 Int_t level = GetLevel();
214 Int_t level2 = ((AliAlignObj *)obj)->GetLevel();
218 return ((level > level2) ? 1 : -1);
221 //_____________________________________________________________________________
222 void AliAlignObj::AnglesToMatrix(const Double_t *angles, Double_t *rot) const
224 // Calculates the rotation matrix using the
225 // Euler angles in "x y z" notation
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]);
235 rot[0] = costhe*cosphi;
236 rot[1] = -costhe*sinphi;
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;
246 //_____________________________________________________________________________
247 Bool_t AliAlignObj::MatrixToAngles(const Double_t *rot, Double_t *angles) const
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
254 if(TMath::Abs(rot[0])<1e-7 || TMath::Abs(rot[8])<1e-7) {
255 AliError("Failed to extract roll-pitch-yall angles!");
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]);
265 //______________________________________________________________________________
266 void AliAlignObj::Transform(AliTrackPoint &p) const
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
273 if (fVolUID != p.GetVolumeID())
274 AliWarning(Form("Alignment object ID is not equal to the space-point ID (%d != %d)",fVolUID,p.GetVolumeID()));
278 Double_t *rot = m.GetRotationMatrix();
279 Double_t *tr = m.GetTranslation();
281 Float_t xyzin[3],xyzout[3];
283 for (Int_t i = 0; i < 3; i++)
292 //_____________________________________________________________________________
293 void AliAlignObj::Transform(AliTrackPointArray &array) const
295 // This method is used to transform all the track points
296 // from the input AliTrackPointArray
299 for (Int_t i = 0; i < array.GetNPoints(); i++) {
302 array.AddPoint(i,&p);
306 //_____________________________________________________________________________
307 void AliAlignObj::Print(Option_t *) const
309 // Print the contents of the
310 // alignment object in angles and
311 // matrix representations
319 const Double_t *rot = m.GetRotationMatrix();
321 printf("Volume=%s\n",GetSymName());
322 if (GetVolUID() != 0) {
325 GetVolUID(layerId,modId);
326 printf("VolumeID=%d LayerID=%d ( %s ) ModuleID=%d\n", GetVolUID(),layerId,LayerName(layerId),modId);
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]);
334 //_____________________________________________________________________________
335 Int_t AliAlignObj::LayerSize(Int_t layerId)
337 // Get the layer size for layer corresponding to layerId.
338 // Implemented only for ITS,TPC,TRD,TOF and HMPID
340 if (layerId < kFirstLayer || layerId >= kLastLayer) {
341 AliErrorClass(Form("Invalid layer index %d ! Layer range is (%d -> %d) !",layerId,kFirstLayer,kLastLayer));
345 return fgLayerSize[layerId - kFirstLayer];
349 //_____________________________________________________________________________
350 const char* AliAlignObj::LayerName(Int_t layerId)
352 // Get the layer name corresponding to layerId.
353 // Implemented only for ITS,TPC,TRD,TOF and HMPID
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!";
360 return fgLayerName[layerId - kFirstLayer];
364 //_____________________________________________________________________________
365 UShort_t AliAlignObj::LayerToVolUID(ELayerID layerId, Int_t modId)
367 // From detector (layer) name and module number (according to detector
368 // internal numbering) build the unique numerical identity of that volume
370 // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
371 // remaining 11 for module ID inside det (2048 possible values).
373 return ((UShort_t(layerId) << 11) | UShort_t(modId));
376 //_____________________________________________________________________________
377 UShort_t AliAlignObj::LayerToVolUID(Int_t layerId, Int_t modId)
379 // From detector (layer) name and module number (according to detector
380 // internal numbering) build the unique numerical identity of that volume
382 // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
383 // remaining 11 for module ID inside det (2048 possible values).
385 return ((UShort_t(layerId) << 11) | UShort_t(modId));
388 //_____________________________________________________________________________
389 AliAlignObj::ELayerID AliAlignObj::VolUIDToLayer(UShort_t voluid, Int_t &modId)
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.
397 modId = voluid & 0x7ff;
399 return VolUIDToLayer(voluid);
402 //_____________________________________________________________________________
403 AliAlignObj::ELayerID AliAlignObj::VolUIDToLayer(UShort_t voluid)
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
410 return ELayerID((voluid >> 11) & 0x1f);
413 //_____________________________________________________________________________
414 void AliAlignObj::SetPars(Double_t x, Double_t y, Double_t z,
415 Double_t psi, Double_t theta, Double_t phi)
417 // Set the global delta transformation by passing 3 angles (expressed in
418 // degrees) and 3 shifts (in centimeters)
420 SetTranslation(x,y,z);
421 SetRotation(psi,theta,phi);
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)
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.
434 Double_t tr[3] = {x, y, z};
435 m.SetTranslation(tr);
436 Double_t angles[3] = {psi, theta, phi};
438 AnglesToMatrix(angles,rot);
441 return SetLocalMatrix(m);
445 //_____________________________________________________________________________
446 Bool_t AliAlignObj::SetLocalTranslation(Double_t x, Double_t y, Double_t z)
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.
455 Double_t tr[3] = {x, y, z};
456 m.SetTranslation(tr);
458 return SetLocalMatrix(m);
462 //_____________________________________________________________________________
463 Bool_t AliAlignObj::SetLocalTranslation(const TGeoMatrix& m)
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.
470 const Double_t* tr = m.GetTranslation();
472 mtr.SetTranslation(tr);
474 return SetLocalMatrix(mtr);
478 //_____________________________________________________________________________
479 Bool_t AliAlignObj::SetLocalRotation(Double_t psi, Double_t theta, Double_t phi)
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.
488 Double_t angles[3] = {psi, theta, phi};
490 AnglesToMatrix(angles,rot);
493 return SetLocalMatrix(m);
497 //_____________________________________________________________________________
498 Bool_t AliAlignObj::SetLocalRotation(const TGeoMatrix& m)
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.
506 const Double_t* rot = m.GetRotationMatrix();
507 rotm.SetRotation(rot);
509 return SetLocalMatrix(rotm);
513 //_____________________________________________________________________________
514 Bool_t AliAlignObj::SetLocalMatrix(const TGeoMatrix& m)
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.
521 if (!gGeoManager || !gGeoManager->IsClosed()) {
522 AliError("Can't set the alignment object parameters! gGeoManager doesn't exist or it is still opened!");
526 const char* symname = GetSymName();
527 TGeoPhysicalNode* node;
528 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
530 node = gGeoManager->MakeAlignablePN(pne);
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);
537 AliError(Form("Volume name or path %s not valid!",symname));
540 if (node->IsAligned())
541 AliWarning(Form("Volume %s has been already misaligned!",symname));
544 const Double_t *tr = m.GetTranslation();
545 m1.SetTranslation(tr);
546 const Double_t* rot = m.GetRotationMatrix();
549 TGeoHMatrix align,gprime,gprimeinv;
550 gprime = *node->GetMatrix();
551 gprimeinv = gprime.Inverse();
552 m1.Multiply(&gprimeinv);
553 m1.MultiplyLeft(&gprime);
555 return SetMatrix(m1);
558 //_____________________________________________________________________________
559 Bool_t AliAlignObj::SetMatrix(const TGeoMatrix& m)
561 // Set the global delta transformation by passing the TGeoMatrix
565 return SetRotation(m);
568 //_____________________________________________________________________________
569 Bool_t AliAlignObj::GetLocalPars(Double_t transl[], Double_t angles[]) const
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.
576 if(!GetLocalTranslation(transl)) return kFALSE;
577 return GetLocalAngles(angles);
580 //_____________________________________________________________________________
581 Bool_t AliAlignObj::GetLocalTranslation(Double_t* tr) const
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.
589 if(!GetLocalMatrix(ml)) return kFALSE;
590 const Double_t* transl;
591 transl = ml.GetTranslation();
598 //_____________________________________________________________________________
599 Bool_t AliAlignObj::GetLocalAngles(Double_t* angles) const
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.
607 if(!GetLocalMatrix(ml)) return kFALSE;
608 const Double_t *rot = ml.GetRotationMatrix();
609 return MatrixToAngles(rot,angles);
612 //_____________________________________________________________________________
613 Bool_t AliAlignObj::GetLocalMatrix(TGeoHMatrix& m) const
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.
619 if (!gGeoManager || !gGeoManager->IsClosed()) {
620 AliError("Can't set the alignment object parameters! gGeoManager doesn't exist or it is still opened!");
624 const char* symname = GetSymName();
625 TGeoPhysicalNode* node;
626 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
628 node = gGeoManager->MakeAlignablePN(pne);
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);
635 AliError(Form("Volume name or path %s not valid!",symname));
638 if (node->IsAligned())
639 AliWarning(Form("Volume %s has been already misaligned!",symname));
642 TGeoHMatrix gprime,gprimeinv;
643 gprime = *node->GetMatrix();
644 gprimeinv = gprime.Inverse();
646 m.MultiplyLeft(&gprimeinv);
651 //_____________________________________________________________________________
652 Bool_t AliAlignObj::ApplyToGeometry()
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
658 if (!gGeoManager || !gGeoManager->IsClosed()) {
659 AliError("Can't apply the alignment object! gGeoManager doesn't exist or it is still opened!");
663 const char* symname = GetSymName();
665 TGeoPhysicalNode* node;
666 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
668 path = pne->GetTitle();
669 node = gGeoManager->MakeAlignablePN(pne);
671 AliDebug(1,Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
673 if (!gGeoManager->CheckPath(path)) {
674 AliDebug(1,Form("Volume path %s not valid!",path));
677 if (gGeoManager->GetListOfPhysicalNodes()->FindObject(path)) {
678 AliError(Form("Volume %s has already been misaligned!",path));
681 node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(path);
685 AliError(Form("Volume path %s not valid!",path));
689 TGeoHMatrix align,gprime;
690 gprime = *node->GetMatrix();
692 gprime.MultiplyLeft(&align);
693 TGeoHMatrix *ginv = new TGeoHMatrix;
694 TGeoHMatrix *g = node->GetMatrix(node->GetLevel()-1);
695 *ginv = g->Inverse();
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));
706 //_____________________________________________________________________________
707 Bool_t AliAlignObj::GetFromGeometry(const char *symname, AliAlignObj &alobj)
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.
718 // Reset the alignment object
719 alobj.SetPars(0,0,0,0,0,0);
720 alobj.SetSymName(symname);
722 if (!gGeoManager || !gGeoManager->IsClosed()) {
723 AliErrorClass("Can't get the alignment object! gGeoManager doesn't exist or it is still opened!");
727 if (!gGeoManager->GetListOfPhysicalNodes()) {
728 AliErrorClass("Can't get the alignment object! gGeoManager doesn't contain any aligned nodes!");
733 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
735 path = pne->GetTitle();
737 AliWarningClass(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
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) {
752 if (!gGeoManager->cd(path)) {
753 AliErrorClass(Form("%s not valid neither as symbolic volume name nor as volume path!",path));
757 AliWarningClass(Form("Volume (%s) has not been misaligned!",path));
762 TGeoHMatrix align,gprime,g,ginv,l;
763 gprime = *node->GetMatrix();
764 l = *node->GetOriginalMatrix();
765 g = *node->GetMatrix(node->GetLevel()-1);
768 align = gprime * ginv;
770 return alobj.SetMatrix(align);
773 //_____________________________________________________________________________
774 Bool_t AliAlignObj::GetOrigGlobalMatrix(const char *symname, TGeoHMatrix &m)
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
783 if (!gGeoManager || !gGeoManager->IsClosed()) {
784 AliErrorClass("Can't get the original global matrix! gGeoManager doesn't exist or it is still opened!");
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));
795 m = *gGeoManager->GetCurrentMatrix();
800 const char* path = NULL;
801 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
803 path = pne->GetTitle();
805 AliWarningClass(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
809 if (!gGeoManager->CheckPath(path)) {
810 AliErrorClass(Form("Volume path %s not valid!",path));
816 TIter next(gGeoManager->GetListOfPhysicalNodes());
817 gGeoManager->cd(path);
819 while(gGeoManager->GetLevel()){
821 TGeoPhysicalNode *physNode = NULL;
823 TGeoNode *node = gGeoManager->GetCurrentNode();
824 while ((physNode=(TGeoPhysicalNode*)next()))
825 if (physNode->GetNode() == node) break;
827 TGeoMatrix *lm = NULL;
829 lm = physNode->GetOriginalMatrix();
830 if (!lm) lm = node->GetMatrix();
832 lm = node->GetMatrix();
842 //_____________________________________________________________________________
843 void AliAlignObj::InitAlignObjFromGeometry()
845 // Loop over all alignable volumes and extract
846 // the corresponding alignment objects from
849 if(fgAlignObjs[0]) return;
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));
866 //_____________________________________________________________________________
867 AliAlignObj* AliAlignObj::GetAlignObj(UShort_t voluid) {
868 // Returns the alignment object for given volume ID
871 ELayerID layerId = VolUIDToLayer(voluid,modId);
872 return GetAlignObj(layerId,modId);
875 //_____________________________________________________________________________
876 AliAlignObj* AliAlignObj::GetAlignObj(ELayerID layerId, Int_t modId)
878 // Returns pointer to alignment object given its layer and module ID
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));
884 InitAlignObjFromGeometry();
886 return fgAlignObjs[layerId-kFirstLayer][modId];
889 //_____________________________________________________________________________
890 const char* AliAlignObj::SymName(UShort_t voluid) {
891 // Returns the symbolic volume name for given volume ID
894 ELayerID layerId = VolUIDToLayer(voluid,modId);
895 return SymName(layerId,modId);
898 //_____________________________________________________________________________
899 const char* AliAlignObj::SymName(ELayerID layerId, Int_t modId)
901 // Returns the symbolic volume name given for a given layer
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));
910 return fgVolPath[layerId-kFirstLayer][modId].Data();
913 //_____________________________________________________________________________
914 void AliAlignObj::InitSymNames()
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
921 if (fgVolPath[0]) return;
923 for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++)
924 fgVolPath[iLayer] = new TString[fgLayerSize[iLayer]];
927 Int_t modnum; // in the following, set it to 0 at the start of each layer
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;
940 /********************* SPD layer1 ***********************/
944 for(Int_t c1 = 1; c1<=10; c1++){
945 strEntryName1 = strSPD;
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;
957 fgVolPath[kSPD1-kFirstLayer][modnum] = symname.Data();
964 /********************* SPD layer2 ***********************/
968 for(Int_t c1 = 1; c1<=10; c1++){
969 strEntryName1 = strSPD;
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;
981 fgVolPath[kSPD2-kFirstLayer][modnum] = symname.Data();
988 /********************* SDD layer1 ***********************/
992 for(Int_t c1 = 1; c1<=14; c1++){
993 strEntryName1 = strSDD;
995 strEntryName1 +=strLadder;
996 strEntryName1 += (c1-1);
997 for(Int_t c2 =1; c2<=6; c2++){
998 symname = strEntryName1;
999 symname += strSensor;
1001 fgVolPath[kSDD1-kFirstLayer][modnum] = symname.Data();
1007 /********************* SDD layer2 ***********************/
1011 for(Int_t c1 = 1; c1<=22; c1++){
1012 strEntryName1 = strSDD;
1014 strEntryName1 +=strLadder;
1015 strEntryName1 += (c1-1);
1016 for(Int_t c2 = 1; c2<=8; c2++){
1017 symname = strEntryName1;
1018 symname += strSensor;
1020 fgVolPath[kSDD2-kFirstLayer][modnum] = symname.Data();
1026 /********************* SSD layer1 ***********************/
1030 for(Int_t c1 = 1; c1<=34; c1++){
1031 strEntryName1 = strSSD;
1033 strEntryName1 +=strLadder;
1034 strEntryName1 += (c1-1);
1035 for(Int_t c2 = 1; c2<=22; c2++){
1036 symname = strEntryName1;
1037 symname += strSensor;
1039 fgVolPath[kSSD1-kFirstLayer][modnum] = symname.Data();
1045 /********************* SSD layer2 ***********************/
1049 for(Int_t c1 = 1; c1<=38; c1++){
1050 strEntryName1 = strSSD;
1052 strEntryName1 +=strLadder;
1053 strEntryName1 += (c1-1);
1054 for(Int_t c2 = 1; c2<=25; c2++){
1055 symname = strEntryName1;
1056 symname += strSensor;
1058 fgVolPath[kSSD2-kFirstLayer][modnum] = symname.Data();
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";
1071 /*************** TPC inner chambers' layer ****************/
1075 for(Int_t cnt=1; cnt<=18; cnt++){
1079 fgVolPath[kTPC1-kFirstLayer][modnum] = symname.Data();
1082 for(Int_t cnt=1; cnt<=18; cnt++){
1086 fgVolPath[kTPC1-kFirstLayer][modnum] = symname.Data();
1091 /*************** TPC outer chambers' layer ****************/
1095 for(Int_t cnt=1; cnt<=18; cnt++){
1099 fgVolPath[kTPC2-kFirstLayer][modnum] = symname.Data();
1102 for(Int_t cnt=1; cnt<=18; cnt++){
1106 fgVolPath[kTPC2-kFirstLayer][modnum] = symname.Data();
1111 /********************* TOF layer ***********************/
1119 Int_t nStrips=nstrA+2*nstrB+2*nstrC;
1121 TString snSM = "TOF/sm";
1122 TString snSTRIP = "/strip";
1124 for (Int_t isect = 0; isect < nSectors; isect++) {
1125 for (Int_t istr = 1; istr <= nStrips; istr++) {
1127 symname += Form("%02d",isect);
1129 symname += Form("%02d",istr);
1130 fgVolPath[kTOF-kFirstLayer][modnum] = symname.Data();
1136 /********************* HMPID layer ***********************/
1138 TString str = "/HMPID/Chamber";
1140 for (modnum=0; modnum < 7; modnum++) {
1143 fgVolPath[kHMPID-kFirstLayer][modnum] = symname.Data();
1147 /********************* TRD layers 1-6 *******************/
1148 //!! 6 layers with index increasing in outwards direction
1150 Int_t arTRDlayId[6] = {kTRD1, kTRD2, kTRD3, kTRD4, kTRD5, kTRD6};
1152 TString snStr = "TRD/sm";
1153 TString snApp1 = "/st";
1154 TString snApp2 = "/pl";
1156 for(Int_t layer=0; layer<6; layer++){
1158 for (Int_t isect = 0; isect < 18; isect++) {
1159 for (Int_t icham = 0; icham < 5; icham++) {
1161 symname += Form("%02d",isect);
1166 fgVolPath[arTRDlayId[layer]-kFirstLayer][modnum] = symname.Data();