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>
27 #include "TObjString.h"
29 #include "AliAlignObj.h"
30 #include "AliTrackPointArray.h"
32 #include "AliAlignObjAngles.h"
36 Int_t AliAlignObj::fgLayerSize[kLastLayer - kFirstLayer] = {
37 80, 160, // ITS SPD first and second layer
38 84, 176, // ITS SDD first and second layer
39 748, 950, // ITS SSD first and second layer
40 36, 36, // TPC inner and outer chambers
41 90, 90, 90, 90, 90, 90, // 6 TRD chambers' layers
48 const char* AliAlignObj::fgLayerName[kLastLayer - kFirstLayer] = {
49 "ITS inner pixels layer", "ITS outer pixels layer",
50 "ITS inner drifts layer", "ITS outer drifts layer",
51 "ITS inner strips layer", "ITS outer strips layer",
52 "TPC inner chambers layer", "TPC outer chambers layer",
53 "TRD chambers layer 1", "TRD chambers layer 2", "TRD chambers layer 3",
54 "TRD chambers layer 4", "TRD chambers layer 5", "TRD chambers layer 6",
61 TString* AliAlignObj::fgVolPath[kLastLayer - kFirstLayer] = {
74 AliAlignObj** AliAlignObj::fgAlignObjs[kLastLayer - kFirstLayer] = {
87 //_____________________________________________________________________________
88 AliAlignObj::AliAlignObj():
92 // default constructor
96 //_____________________________________________________________________________
97 AliAlignObj::AliAlignObj(const char* symname, UShort_t voluid) :
102 // standard constructor
106 //_____________________________________________________________________________
107 AliAlignObj::AliAlignObj(const AliAlignObj& theAlignObj) :
108 TObject(theAlignObj),
109 fVolPath(theAlignObj.GetSymName()),
110 fVolUID(theAlignObj.GetVolUID())
115 //_____________________________________________________________________________
116 AliAlignObj &AliAlignObj::operator =(const AliAlignObj& theAlignObj)
118 // assignment operator
119 if(this==&theAlignObj) return *this;
120 fVolPath = theAlignObj.GetSymName();
121 fVolUID = theAlignObj.GetVolUID();
125 //_____________________________________________________________________________
126 AliAlignObj &AliAlignObj::operator*=(const AliAlignObj& theAlignObj)
128 // multiplication operator
129 // The operator can be used to 'combine'
130 // two alignment objects
134 theAlignObj.GetMatrix(m2);
135 m1.MultiplyLeft(&m2);
140 //_____________________________________________________________________________
141 AliAlignObj::~AliAlignObj()
146 //_____________________________________________________________________________
147 void AliAlignObj::SetVolUID(ELayerID detId, Int_t modId)
149 // From detector name and module number (according to detector numbering)
150 // build fVolUID, unique numerical identity of that volume inside ALICE
151 // fVolUID is 16 bits, first 5 reserved for detID (32 possible values),
152 // remaining 11 for module ID inside det (2048 possible values).
154 fVolUID = LayerToVolUID(detId,modId);
157 //_____________________________________________________________________________
158 void AliAlignObj::GetVolUID(ELayerID &layerId, Int_t &modId) const
160 // From the fVolUID, unique numerical identity of that volume inside ALICE,
161 // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
162 // remaining 11 for module ID inside det (2048 possible values)), sets
163 // the argument layerId to the identity of the layer to which that volume
164 // belongs and sets the argument modId to the identity of that volume
165 // internally to the layer.
167 layerId = VolUIDToLayer(fVolUID,modId);
170 //_____________________________________________________________________________
171 Bool_t AliAlignObj::GetPars(Double_t tr[], Double_t angles[]) const
174 return GetAngles(angles);
177 //_____________________________________________________________________________
178 Int_t AliAlignObj::GetLevel() const
180 // Return the geometry level of the alignable volume to which
181 // the alignment object is associated; this is the number of
182 // slashes in the corresponding volume path
185 AliWarning("gGeoManager doesn't exist or it is still opened: unable to return meaningful level value.");
188 const char* symname = GetSymName();
190 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
192 path = pne->GetTitle();
197 TString path_str = path;
198 if(path_str[0]!='/') path_str.Prepend('/');
199 return path_str.CountChar('/');
202 //_____________________________________________________________________________
203 Int_t AliAlignObj::Compare(const TObject *obj) const
205 // Compare the levels of two
207 // Used in the sorting during
208 // the application of alignment
209 // objects to the geometry
211 Int_t level = GetLevel();
212 Int_t level2 = ((AliAlignObj *)obj)->GetLevel();
216 return ((level > level2) ? 1 : -1);
219 //_____________________________________________________________________________
220 void AliAlignObj::AnglesToMatrix(const Double_t *angles, Double_t *rot) const
222 // Calculates the rotation matrix using the
223 // Euler angles in "x y z" notation
225 Double_t degrad = TMath::DegToRad();
226 Double_t sinpsi = TMath::Sin(degrad*angles[0]);
227 Double_t cospsi = TMath::Cos(degrad*angles[0]);
228 Double_t sinthe = TMath::Sin(degrad*angles[1]);
229 Double_t costhe = TMath::Cos(degrad*angles[1]);
230 Double_t sinphi = TMath::Sin(degrad*angles[2]);
231 Double_t cosphi = TMath::Cos(degrad*angles[2]);
233 rot[0] = costhe*cosphi;
234 rot[1] = -costhe*sinphi;
236 rot[3] = sinpsi*sinthe*cosphi + cospsi*sinphi;
237 rot[4] = -sinpsi*sinthe*sinphi + cospsi*cosphi;
238 rot[5] = -costhe*sinpsi;
239 rot[6] = -cospsi*sinthe*cosphi + sinpsi*sinphi;
240 rot[7] = cospsi*sinthe*sinphi + sinpsi*cosphi;
241 rot[8] = costhe*cospsi;
244 //_____________________________________________________________________________
245 Bool_t AliAlignObj::MatrixToAngles(const Double_t *rot, Double_t *angles) const
247 // Calculates the Euler angles in "x y z" notation
248 // using the rotation matrix
249 // Returns false in case the rotation angles can not be
250 // extracted from the matrix
252 if(TMath::Abs(rot[0])<1e-7 || TMath::Abs(rot[8])<1e-7) {
253 AliError("Failed to extract roll-pitch-yall angles!");
256 Double_t raddeg = TMath::RadToDeg();
257 angles[0]=raddeg*TMath::ATan2(-rot[5],rot[8]);
258 angles[1]=raddeg*TMath::ASin(rot[2]);
259 angles[2]=raddeg*TMath::ATan2(-rot[1],rot[0]);
263 //______________________________________________________________________________
264 void AliAlignObj::Transform(AliTrackPoint &p) const
266 // The method transforms the space-point coordinates using the
267 // transformation matrix provided by the AliAlignObj
268 // The covariance matrix is not affected since we assume
269 // that the transformations are sufficiently small
271 if (fVolUID != p.GetVolumeID())
272 AliWarning(Form("Alignment object ID is not equal to the space-point ID (%d != %d)",fVolUID,p.GetVolumeID()));
276 Double_t *rot = m.GetRotationMatrix();
277 Double_t *tr = m.GetTranslation();
279 Float_t xyzin[3],xyzout[3];
281 for (Int_t i = 0; i < 3; i++)
290 //_____________________________________________________________________________
291 void AliAlignObj::Transform(AliTrackPointArray &array) const
293 // This method is used to transform all the track points
294 // from the input AliTrackPointArray
297 for (Int_t i = 0; i < array.GetNPoints(); i++) {
300 array.AddPoint(i,&p);
304 //_____________________________________________________________________________
305 void AliAlignObj::Print(Option_t *) const
307 // Print the contents of the
308 // alignment object in angles and
309 // matrix representations
317 const Double_t *rot = m.GetRotationMatrix();
319 printf("Volume=%s\n",GetSymName());
320 if (GetVolUID() != 0) {
323 GetVolUID(layerId,modId);
324 printf("VolumeID=%d LayerID=%d ( %s ) ModuleID=%d\n", GetVolUID(),layerId,LayerName(layerId),modId);
326 printf("%12.8f%12.8f%12.8f Tx = %12.8f Psi = %12.8f\n", rot[0], rot[1], rot[2], tr[0], angles[0]);
327 printf("%12.8f%12.8f%12.8f Ty = %12.8f Theta = %12.8f\n", rot[3], rot[4], rot[5], tr[1], angles[1]);
328 printf("%12.8f%12.8f%12.8f Tz = %12.8f Phi = %12.8f\n", rot[6], rot[7], rot[8], tr[2], angles[2]);
332 //_____________________________________________________________________________
333 Int_t AliAlignObj::LayerSize(Int_t layerId)
335 // Get the layer size for layer corresponding to layerId.
336 // Implemented only for ITS,TPC,TRD,TOF and HMPID
338 if (layerId < kFirstLayer || layerId >= kLastLayer) {
339 AliErrorClass(Form("Invalid layer index %d ! Layer range is (%d -> %d) !",layerId,kFirstLayer,kLastLayer));
343 return fgLayerSize[layerId - kFirstLayer];
347 //_____________________________________________________________________________
348 const char* AliAlignObj::LayerName(Int_t layerId)
350 // Get the layer name corresponding to layerId.
351 // Implemented only for ITS,TPC,TRD,TOF and HMPID
353 if (layerId < kFirstLayer || layerId >= kLastLayer) {
354 AliErrorClass(Form("Invalid layer index %d ! Layer range is (%d -> %d) !",layerId,kFirstLayer,kLastLayer));
355 return "Invalid Layer!";
358 return fgLayerName[layerId - kFirstLayer];
362 //_____________________________________________________________________________
363 UShort_t AliAlignObj::LayerToVolUID(ELayerID layerId, Int_t modId)
365 // From detector (layer) name and module number (according to detector
366 // internal numbering) build the unique numerical identity of that volume
368 // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
369 // remaining 11 for module ID inside det (2048 possible values).
371 return ((UShort_t(layerId) << 11) | UShort_t(modId));
374 //_____________________________________________________________________________
375 UShort_t AliAlignObj::LayerToVolUID(Int_t layerId, Int_t modId)
377 // From detector (layer) name and module number (according to detector
378 // internal numbering) build the unique numerical identity of that volume
380 // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
381 // remaining 11 for module ID inside det (2048 possible values).
383 return ((UShort_t(layerId) << 11) | UShort_t(modId));
386 //_____________________________________________________________________________
387 AliAlignObj::ELayerID AliAlignObj::VolUIDToLayer(UShort_t voluid, Int_t &modId)
389 // From voluid, unique numerical identity of that volume inside ALICE,
390 // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
391 // remaining 11 for module ID inside det (2048 possible values)), return
392 // the identity of the layer to which that volume belongs and sets the
393 // argument modId to the identity of that volume internally to the layer.
395 modId = voluid & 0x7ff;
397 return VolUIDToLayer(voluid);
400 //_____________________________________________________________________________
401 AliAlignObj::ELayerID AliAlignObj::VolUIDToLayer(UShort_t voluid)
403 // From voluid, unique numerical identity of that volume inside ALICE,
404 // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
405 // remaining 11 for module ID inside det (2048 possible values)), return
406 // the identity of the layer to which that volume belongs
408 return ELayerID((voluid >> 11) & 0x1f);
411 //_____________________________________________________________________________
412 void AliAlignObj::SetPars(Double_t x, Double_t y, Double_t z,
413 Double_t psi, Double_t theta, Double_t phi)
415 // Set the global delta transformation by passing 3 angles (expressed in
416 // degrees) and 3 shifts (in centimeters)
418 SetTranslation(x,y,z);
419 SetRotation(psi,theta,phi);
422 //_____________________________________________________________________________
423 Bool_t AliAlignObj::SetLocalPars(Double_t x, Double_t y, Double_t z,
424 Double_t psi, Double_t theta, Double_t phi)
426 // Set the global delta transformation by passing the parameters
427 // for the local delta transformation (3 shifts and 3 angles).
428 // In case that the TGeo was not initialized or not closed,
429 // returns false and the object parameters are not set.
432 Double_t tr[3] = {x, y, z};
433 m.SetTranslation(tr);
434 Double_t angles[3] = {psi, theta, phi};
436 AnglesToMatrix(angles,rot);
439 return SetLocalMatrix(m);
443 //_____________________________________________________________________________
444 Bool_t AliAlignObj::SetLocalTranslation(Double_t x, Double_t y, Double_t z)
446 // Set the global delta transformation by passing the three shifts giving
447 // the translation in the local reference system of the alignable
448 // volume (known by TGeo geometry).
449 // In case that the TGeo was not initialized or not closed,
450 // returns false and the object parameters are not set.
453 Double_t tr[3] = {x, y, z};
454 m.SetTranslation(tr);
456 return SetLocalMatrix(m);
460 //_____________________________________________________________________________
461 Bool_t AliAlignObj::SetLocalTranslation(const TGeoMatrix& m)
463 // Set the global delta transformation by passing the matrix of
464 // the local delta transformation and taking its translational part
465 // In case that the TGeo was not initialized or not closed,
466 // returns false and the object parameters are not set.
468 const Double_t* tr = m.GetTranslation();
470 mtr.SetTranslation(tr);
472 return SetLocalMatrix(mtr);
476 //_____________________________________________________________________________
477 Bool_t AliAlignObj::SetLocalRotation(Double_t psi, Double_t theta, Double_t phi)
479 // Set the global delta transformation by passing the three angles giving
480 // the rotation in the local reference system of the alignable
481 // volume (known by TGeo geometry).
482 // In case that the TGeo was not initialized or not closed,
483 // returns false and the object parameters are not set.
486 Double_t angles[3] = {psi, theta, phi};
488 AnglesToMatrix(angles,rot);
491 return SetLocalMatrix(m);
495 //_____________________________________________________________________________
496 Bool_t AliAlignObj::SetLocalRotation(const TGeoMatrix& m)
498 // Set the global delta transformation by passing the matrix of
499 // the local delta transformation and taking its rotational part
500 // In case that the TGeo was not initialized or not closed,
501 // returns false and the object parameters are not set.
504 const Double_t* rot = m.GetRotationMatrix();
505 rotm.SetRotation(rot);
507 return SetLocalMatrix(rotm);
511 //_____________________________________________________________________________
512 Bool_t AliAlignObj::SetLocalMatrix(const TGeoMatrix& m)
514 // Set the global delta transformation by passing the TGeo matrix
515 // for the local delta transformation.
516 // In case that the TGeo was not initialized or not closed,
517 // returns false and the object parameters are not set.
519 if (!gGeoManager || !gGeoManager->IsClosed()) {
520 AliError("Can't set the alignment object parameters! gGeoManager doesn't exist or it is still opened!");
524 const char* symname = GetSymName();
525 TGeoPhysicalNode* node;
526 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
528 node = gGeoManager->MakeAlignablePN(pne);
530 AliWarning(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as volume path!",symname));
531 node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(symname);
535 AliError(Form("Volume name or path %s not valid!",symname));
538 if (node->IsAligned())
539 AliWarning(Form("Volume %s has been already misaligned!",symname));
542 const Double_t *tr = m.GetTranslation();
543 m1.SetTranslation(tr);
544 const Double_t* rot = m.GetRotationMatrix();
547 TGeoHMatrix align,gprime,gprimeinv;
548 gprime = *node->GetMatrix();
549 gprimeinv = gprime.Inverse();
550 m1.Multiply(&gprimeinv);
551 m1.MultiplyLeft(&gprime);
553 return SetMatrix(m1);
556 //_____________________________________________________________________________
557 Bool_t AliAlignObj::SetMatrix(const TGeoMatrix& m)
559 // Set the global delta transformation by passing the TGeoMatrix
563 return SetRotation(m);
566 //_____________________________________________________________________________
567 Bool_t AliAlignObj::GetLocalPars(Double_t transl[], Double_t angles[]) const
569 // Get the translations and angles (in degrees) expressing the
570 // local delta transformation.
571 // In case that the TGeo was not initialized or not closed,
572 // returns false and the object parameters are not set.
574 if(!GetLocalTranslation(transl)) return kFALSE;
575 return GetLocalAngles(angles);
578 //_____________________________________________________________________________
579 Bool_t AliAlignObj::GetLocalTranslation(Double_t* tr) const
581 // Get the 3 shifts giving the translational part of the local
582 // delta transformation.
583 // In case that the TGeo was not initialized or not closed,
584 // returns false and the object parameters are not set.
587 if(!GetLocalMatrix(ml)) return kFALSE;
588 const Double_t* transl;
589 transl = ml.GetTranslation();
596 //_____________________________________________________________________________
597 Bool_t AliAlignObj::GetLocalAngles(Double_t* angles) const
599 // Get the 3 angles giving the rotational part of the local
600 // delta transformation.
601 // In case that the TGeo was not initialized or not closed,
602 // returns false and the object parameters are not set.
605 if(!GetLocalMatrix(ml)) return kFALSE;
606 const Double_t *rot = ml.GetRotationMatrix();
607 return MatrixToAngles(rot,angles);
610 //_____________________________________________________________________________
611 Bool_t AliAlignObj::GetLocalMatrix(TGeoHMatrix& m) const
613 // Get the matrix for the local delta transformation.
614 // In case that the TGeo was not initialized or not closed,
615 // returns false and the object parameters are not set.
617 if (!gGeoManager || !gGeoManager->IsClosed()) {
618 AliError("Can't set the alignment object parameters! gGeoManager doesn't exist or it is still opened!");
622 const char* symname = GetSymName();
623 TGeoPhysicalNode* node;
624 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
626 node = gGeoManager->MakeAlignablePN(pne);
628 AliWarning(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as volume path!",symname));
629 node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(symname);
633 AliError(Form("Volume name or path %s not valid!",symname));
636 if (node->IsAligned())
637 AliWarning(Form("Volume %s has been already misaligned!",symname));
640 TGeoHMatrix gprime,gprimeinv;
641 gprime = *node->GetMatrix();
642 gprimeinv = gprime.Inverse();
644 m.MultiplyLeft(&gprimeinv);
649 //_____________________________________________________________________________
650 Bool_t AliAlignObj::ApplyToGeometry()
652 // Apply the current alignment object to the TGeo geometry
653 // This method returns FALSE if the symname of the object was not
654 // valid neither to get a TGeoPEntry nor as a volume path
656 if (!gGeoManager || !gGeoManager->IsClosed()) {
657 AliError("Can't apply the alignment object! gGeoManager doesn't exist or it is still opened!");
661 const char* symname = GetSymName();
663 TGeoPhysicalNode* node;
664 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
666 path = pne->GetTitle();
667 node = gGeoManager->MakeAlignablePN(pne);
669 AliWarning(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
671 if (!gGeoManager->CheckPath(path)) {
672 AliError(Form("Volume path %s not valid!",path));
675 if (gGeoManager->GetListOfPhysicalNodes()->FindObject(path)) {
676 AliError(Form("Volume %s has already been misaligned!",path));
679 node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(path);
683 AliError(Form("Volume path %s not valid!",path));
687 TGeoHMatrix align,gprime;
688 gprime = *node->GetMatrix();
690 gprime.MultiplyLeft(&align);
691 TGeoHMatrix *ginv = new TGeoHMatrix;
692 TGeoHMatrix *g = node->GetMatrix(node->GetLevel()-1);
693 *ginv = g->Inverse();
695 AliAlignObj::ELayerID layerId; // unique identity for layer in the alobj
696 Int_t modId; // unique identity for volume inside layer in the alobj
697 GetVolUID(layerId, modId);
698 AliDebug(2,Form("Aligning volume %s of detector layer %d with local ID %d",symname,layerId,modId));
704 //_____________________________________________________________________________
705 Bool_t AliAlignObj::GetFromGeometry(const char *symname, AliAlignObj &alobj)
707 // Get the alignment object which corresponds to the symbolic volume name
708 // symname (in case equal to the TGeo volume path)
709 // The method is extremely slow due to the searching by string.
710 // Therefore it should be used with great care!!
711 // This method returns FALSE if the symname of the object was not
712 // valid neither to get a TGeoPEntry nor as a volume path, or if the path
713 // associated to the TGeoPNEntry was not valid.
716 // Reset the alignment object
717 alobj.SetPars(0,0,0,0,0,0);
718 alobj.SetSymName(symname);
720 if (!gGeoManager || !gGeoManager->IsClosed()) {
721 AliErrorClass("Can't get the alignment object! gGeoManager doesn't exist or it is still opened!");
725 if (!gGeoManager->GetListOfPhysicalNodes()) {
726 AliErrorClass("Can't get the alignment object! gGeoManager doesn't contain any aligned nodes!");
731 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
733 path = pne->GetTitle();
735 AliWarningClass(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
738 TObjArray* nodesArr = gGeoManager->GetListOfPhysicalNodes();
739 TGeoPhysicalNode* node = NULL;
740 for (Int_t iNode = 0; iNode < nodesArr->GetEntriesFast(); iNode++) {
741 TGeoPhysicalNode* tempNode = (TGeoPhysicalNode*) nodesArr->UncheckedAt(iNode);
742 const char *nodePath = tempNode->GetName();
743 if (strcmp(path,nodePath) == 0) {
750 if (!gGeoManager->cd(path)) {
751 AliErrorClass(Form("%s not valid neither as symbolic volume name nor as volume path!",path));
755 AliWarningClass(Form("Volume (%s) has not been misaligned!",path));
760 TGeoHMatrix align,gprime,g,ginv,l;
761 gprime = *node->GetMatrix();
762 l = *node->GetOriginalMatrix();
763 g = *node->GetMatrix(node->GetLevel()-1);
766 align = gprime * ginv;
768 return alobj.SetMatrix(align);
771 //_____________________________________________________________________________
772 Bool_t AliAlignObj::GetOrigGlobalMatrix(const char *symname, TGeoHMatrix &m)
774 // The method returns global matrix for the ideal detector geometry
775 // Symname identifies either the corresponding TGeoPNEntry or directly
776 // the volume path. The output global matrix is stored in 'm'.
777 // Returns kFALSE in case, TGeo has not been initialized or the symname
781 if (!gGeoManager || !gGeoManager->IsClosed()) {
782 AliErrorClass("Can't get the original global matrix! gGeoManager doesn't exist or it is still opened!");
786 if (!gGeoManager->GetListOfPhysicalNodes()) {
787 AliWarningClass("gGeoManager doesn't contain any aligned nodes!");
788 if (!gGeoManager->cd(symname)) {
789 AliErrorClass(Form("Volume path %s not valid!",symname));
793 m = *gGeoManager->GetCurrentMatrix();
798 const char* path = NULL;
799 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
801 path = pne->GetTitle();
803 AliWarningClass(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
807 if (!gGeoManager->CheckPath(path)) {
808 AliErrorClass(Form("Volume path %s not valid!",path));
812 TString pathStr = path;
813 TObjArray *pathArr = pathStr.Tokenize('/');
815 TString nodeStr = "";
818 TObjString *str = NULL;
819 while((str = (TObjString*) iter.Next())){
821 nodeStr.Append(str->String());
823 TGeoMatrix *lm = NULL;
824 if (TGeoPhysicalNode *physNode = (TGeoPhysicalNode *)gGeoManager->GetListOfPhysicalNodes()->FindObject(nodeStr.Data())) {
825 lm = physNode->GetOriginalMatrix();
826 if (!lm) lm = physNode->GetNode()->GetMatrix();
829 gGeoManager->cd(nodeStr.Data());
830 TGeoNode *node = gGeoManager->GetCurrentNode();
831 lm = node->GetMatrix();
841 //_____________________________________________________________________________
842 void AliAlignObj::InitAlignObjFromGeometry()
844 // Loop over all alignable volumes and extract
845 // the corresponding alignment objects from
848 if(fgAlignObjs[0]) return;
852 for (Int_t iLayer = kFirstLayer; iLayer < AliAlignObj::kLastLayer; iLayer++) {
853 fgAlignObjs[iLayer-kFirstLayer] = new AliAlignObj*[AliAlignObj::LayerSize(iLayer)];
854 for (Int_t iModule = 0; iModule < AliAlignObj::LayerSize(iLayer); iModule++) {
855 UShort_t volid = AliAlignObj::LayerToVolUID(iLayer,iModule);
856 fgAlignObjs[iLayer-kFirstLayer][iModule] = new AliAlignObjAngles("",volid,0,0,0,0,0,0,kTRUE);
857 const char *symname = SymName(volid);
858 if (!GetFromGeometry(symname, *fgAlignObjs[iLayer-kFirstLayer][iModule]))
859 AliErrorClass(Form("Failed to extract the alignment object for the volume (ID=%d and path=%s) !",volid,symname));
865 //_____________________________________________________________________________
866 AliAlignObj* AliAlignObj::GetAlignObj(UShort_t voluid) {
867 // Returns the alignment object for given volume ID
870 ELayerID layerId = VolUIDToLayer(voluid,modId);
871 return GetAlignObj(layerId,modId);
874 //_____________________________________________________________________________
875 AliAlignObj* AliAlignObj::GetAlignObj(ELayerID layerId, Int_t modId)
877 // Returns pointer to alignment object given its layer and module ID
879 if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
880 AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
883 InitAlignObjFromGeometry();
885 return fgAlignObjs[layerId-kFirstLayer][modId];
888 //_____________________________________________________________________________
889 const char* AliAlignObj::SymName(UShort_t voluid) {
890 // Returns the symbolic volume name for given volume ID
893 ELayerID layerId = VolUIDToLayer(voluid,modId);
894 return SymName(layerId,modId);
897 //_____________________________________________________________________________
898 const char* AliAlignObj::SymName(ELayerID layerId, Int_t modId)
900 // Returns the symbolic volume name given for a given layer
903 if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
904 AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
909 return fgVolPath[layerId-kFirstLayer][modId].Data();
912 //_____________________________________________________________________________
913 void AliAlignObj::InitSymNames()
915 // Initialize the LUTs which associate the symbolic volume names
916 // for each alignable volume with their unique numerical identity.
917 // The LUTs are static, so they are created during the instantiation
918 // of the first intance of AliAlignObj
920 if (fgVolPath[0]) return;
922 for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++)
923 fgVolPath[iLayer] = new TString[fgLayerSize[iLayer]];
926 Int_t modnum; // in the following, set it to 0 at the start of each layer
928 /********************* ITS layers ***********************/
929 TString strSPD = "ITS/SPD";
930 TString strSDD = "ITS/SDD";
931 TString strSSD = "ITS/SSD";
932 TString strStave = "/Stave";
933 TString strLadder = "/Ladder";
934 TString strSector = "/Sector";
935 TString strSensor = "/Sensor";
936 TString strEntryName1;
937 TString strEntryName2;
939 /********************* SPD layer1 ***********************/
943 for(Int_t c1 = 1; c1<=10; c1++){
944 strEntryName1 = strSPD;
946 strEntryName1 += strSector;
947 strEntryName1 += (c1-1);
948 for(Int_t c2 =1; c2<=2; c2++){
949 strEntryName2 = strEntryName1;
950 strEntryName2 += strStave;
951 strEntryName2 += (c2-1);
952 for(Int_t c3 =1; c3<=4; c3++){
953 symname = strEntryName2;
954 symname += strLadder;
956 fgVolPath[kSPD1-kFirstLayer][modnum] = symname.Data();
963 /********************* SPD layer2 ***********************/
967 for(Int_t c1 = 1; c1<=10; c1++){
968 strEntryName1 = strSPD;
970 strEntryName1 += strSector;
971 strEntryName1 += (c1-1);
972 for(Int_t c2 =1; c2<=4; c2++){
973 strEntryName2 = strEntryName1;
974 strEntryName2 += strStave;
975 strEntryName2 += (c2-1);
976 for(Int_t c3 =1; c3<=4; c3++){
977 symname = strEntryName2;
978 symname += strLadder;
980 fgVolPath[kSPD2-kFirstLayer][modnum] = symname.Data();
987 /********************* SDD layer1 ***********************/
991 for(Int_t c1 = 1; c1<=14; c1++){
992 strEntryName1 = strSDD;
994 strEntryName1 +=strLadder;
995 strEntryName1 += (c1-1);
996 for(Int_t c2 =1; c2<=6; c2++){
997 symname = strEntryName1;
998 symname += strSensor;
1000 fgVolPath[kSDD1-kFirstLayer][modnum] = symname.Data();
1006 /********************* SDD layer2 ***********************/
1010 for(Int_t c1 = 1; c1<=22; c1++){
1011 strEntryName1 = strSDD;
1013 strEntryName1 +=strLadder;
1014 strEntryName1 += (c1-1);
1015 for(Int_t c2 = 1; c2<=8; c2++){
1016 symname = strEntryName1;
1017 symname += strSensor;
1019 fgVolPath[kSDD2-kFirstLayer][modnum] = symname.Data();
1025 /********************* SSD layer1 ***********************/
1029 for(Int_t c1 = 1; c1<=34; c1++){
1030 strEntryName1 = strSSD;
1032 strEntryName1 +=strLadder;
1033 strEntryName1 += (c1-1);
1034 for(Int_t c2 = 1; c2<=22; c2++){
1035 symname = strEntryName1;
1036 symname += strSensor;
1038 fgVolPath[kSSD1-kFirstLayer][modnum] = symname.Data();
1044 /********************* SSD layer2 ***********************/
1048 for(Int_t c1 = 1; c1<=38; c1++){
1049 strEntryName1 = strSSD;
1051 strEntryName1 +=strLadder;
1052 strEntryName1 += (c1-1);
1053 for(Int_t c2 = 1; c2<=25; c2++){
1054 symname = strEntryName1;
1055 symname += strSensor;
1057 fgVolPath[kSSD2-kFirstLayer][modnum] = symname.Data();
1064 /*************** TPC inner and outer layers ****************/
1065 TString sAsector="TPC/EndcapA/Sector";
1066 TString sCsector="TPC/EndcapC/Sector";
1067 TString sInner="/InnerChamber";
1068 TString sOuter="/OuterChamber";
1070 /*************** TPC inner chambers' layer ****************/
1074 for(Int_t cnt=1; cnt<=18; cnt++){
1078 fgVolPath[kTPC1-kFirstLayer][modnum] = symname.Data();
1081 for(Int_t cnt=1; cnt<=18; cnt++){
1085 fgVolPath[kTPC1-kFirstLayer][modnum] = symname.Data();
1090 /*************** TPC outer chambers' layer ****************/
1094 for(Int_t cnt=1; cnt<=18; cnt++){
1098 fgVolPath[kTPC2-kFirstLayer][modnum] = symname.Data();
1101 for(Int_t cnt=1; cnt<=18; cnt++){
1105 fgVolPath[kTPC2-kFirstLayer][modnum] = symname.Data();
1110 /********************* TOF layer ***********************/
1118 Int_t nStrips=nstrA+2*nstrB+2*nstrC;
1120 TString snSM = "TOF/sm";
1121 TString snSTRIP = "/strip";
1123 for (Int_t isect = 0; isect < nSectors; isect++) {
1124 for (Int_t istr = 1; istr <= nStrips; istr++) {
1126 symname += Form("%02d",isect);
1128 symname += Form("%02d",istr);
1129 fgVolPath[kTOF-kFirstLayer][modnum] = symname.Data();
1135 /********************* HMPID layer ***********************/
1137 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();