]> git.uio.no Git - u/mrichter/AliRoot.git/blame - STEER/AliAlignObj.cxx
Removing the run DB. The information contained in the DB is still stored in the raw...
[u/mrichter/AliRoot.git] / STEER / AliAlignObj.cxx
CommitLineData
c18195b9 1/**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3 * *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
6 * *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
15
16//-----------------------------------------------------------------
7e154d52 17// Implementation of the alignment object class, holding the alignment
18// constants for a single volume, through the abstract class AliAlignObj.
19// From it two derived concrete representation of alignment object class
20// (AliAlignObjAngles, AliAlignObjMatrix) are derived in separate files.
c18195b9 21//-----------------------------------------------------------------
995ad051 22#include <TGeoManager.h>
23#include <TGeoPhysicalNode.h>
24
c18195b9 25#include "AliAlignObj.h"
03b18860 26#include "AliTrackPointArray.h"
27#include "AliLog.h"
c5304981 28#include "AliAlignObjAngles.h"
98937d93 29
c18195b9 30ClassImp(AliAlignObj)
31
98937d93 32Int_t AliAlignObj::fgLayerSize[kLastLayer - kFirstLayer] = {
b760c02e 33 80, 160, // ITS SPD first and second layer
34 84, 176, // ITS SDD first and second layer
35 748, 950, // ITS SSD first and second layer
36 36, 36, // TPC inner and outer chambers
37 90, 90, 90, 90, 90, 90, // 6 TRD chambers' layers
da027ef2 38 1638, // TOF
98937d93 39 1, 1, // PHOS ??
f4b3bbb7 40 7, // HMPID ??
98937d93 41 1 // MUON ??
42};
43
44const char* AliAlignObj::fgLayerName[kLastLayer - kFirstLayer] = {
45 "ITS inner pixels layer", "ITS outer pixels layer",
46 "ITS inner drifts layer", "ITS outer drifts layer",
47 "ITS inner strips layer", "ITS outer strips layer",
48 "TPC inner chambers layer", "TPC outer chambers layer",
49 "TRD chambers layer 1", "TRD chambers layer 2", "TRD chambers layer 3",
50 "TRD chambers layer 4", "TRD chambers layer 5", "TRD chambers layer 6",
51 "TOF layer",
52 "?","?",
f4b3bbb7 53 "HMPID layer",
98937d93 54 "?"
55};
56
7604a026 57TString* AliAlignObj::fgVolPath[kLastLayer - kFirstLayer] = {
03b18860 58 0x0,0x0,
59 0x0,0x0,
60 0x0,0x0,
61 0x0,0x0,
62 0x0,0x0,0x0,
63 0x0,0x0,0x0,
64 0x0,
65 0x0,0x0,
66 0x0,
67 0x0
68};
69
c5304981 70AliAlignObj** AliAlignObj::fgAlignObjs[kLastLayer - kFirstLayer] = {
71 0x0,0x0,
72 0x0,0x0,
73 0x0,0x0,
74 0x0,0x0,
75 0x0,0x0,0x0,
76 0x0,0x0,0x0,
77 0x0,
78 0x0,0x0,
79 0x0,
80 0x0
81};
82
c18195b9 83//_____________________________________________________________________________
84AliAlignObj::AliAlignObj():
fe12e09c 85 fVolPath(),
c18195b9 86 fVolUID(0)
87{
03b18860 88 // default constructor
b760c02e 89 InitSymNames();
c18195b9 90}
91
92//_____________________________________________________________________________
b760c02e 93AliAlignObj::AliAlignObj(const char* symname, UShort_t voluid) :
fe12e09c 94 TObject(),
b760c02e 95 fVolPath(symname),
fe12e09c 96 fVolUID(voluid)
d9cc42ed 97{
98 // standard constructor
99 //
d9cc42ed 100}
101
d9cc42ed 102//_____________________________________________________________________________
c18195b9 103AliAlignObj::AliAlignObj(const AliAlignObj& theAlignObj) :
fe12e09c 104 TObject(theAlignObj),
b760c02e 105 fVolPath(theAlignObj.GetSymName()),
fe12e09c 106 fVolUID(theAlignObj.GetVolUID())
c18195b9 107{
108 //copy constructor
c18195b9 109}
110
111//_____________________________________________________________________________
112AliAlignObj &AliAlignObj::operator =(const AliAlignObj& theAlignObj)
113{
114 // assignment operator
115 if(this==&theAlignObj) return *this;
b760c02e 116 fVolPath = theAlignObj.GetSymName();
c18195b9 117 fVolUID = theAlignObj.GetVolUID();
118 return *this;
119}
120
38b3a170 121//_____________________________________________________________________________
122AliAlignObj &AliAlignObj::operator*=(const AliAlignObj& theAlignObj)
123{
124 // multiplication operator
125 // The operator can be used to 'combine'
126 // two alignment objects
127 TGeoHMatrix m1;
128 GetMatrix(m1);
129 TGeoHMatrix m2;
130 theAlignObj.GetMatrix(m2);
131 m1.MultiplyLeft(&m2);
132 SetMatrix(m1);
133 return *this;
134}
135
c18195b9 136//_____________________________________________________________________________
137AliAlignObj::~AliAlignObj()
138{
139 // dummy destructor
140}
141
befe2c08 142//_____________________________________________________________________________
143void AliAlignObj::SetVolUID(ELayerID detId, Int_t modId)
144{
145 // From detector name and module number (according to detector numbering)
146 // build fVolUID, unique numerical identity of that volume inside ALICE
147 // fVolUID is 16 bits, first 5 reserved for detID (32 possible values),
148 // remaining 11 for module ID inside det (2048 possible values).
149 //
150 fVolUID = LayerToVolUID(detId,modId);
151}
152
153//_____________________________________________________________________________
154void AliAlignObj::GetVolUID(ELayerID &layerId, Int_t &modId) const
155{
7e154d52 156 // From the fVolUID, unique numerical identity of that volume inside ALICE,
157 // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
158 // remaining 11 for module ID inside det (2048 possible values)), sets
159 // the argument layerId to the identity of the layer to which that volume
160 // belongs and sets the argument modId to the identity of that volume
161 // internally to the layer.
befe2c08 162 //
163 layerId = VolUIDToLayer(fVolUID,modId);
164}
165
b760c02e 166//_____________________________________________________________________________
167Bool_t AliAlignObj::GetPars(Double_t tr[], Double_t angles[]) const
168{
169 GetTranslation(tr);
170 return GetAngles(angles);
171}
172
4b94e753 173//_____________________________________________________________________________
174Int_t AliAlignObj::GetLevel() const
175{
85fbf070 176 // Return the geometry level of the alignable volume to which
177 // the alignment object is associated; this is the number of
178 // slashes in the corresponding volume path
179 //
180 if(!gGeoManager){
181 AliWarning("gGeoManager doesn't exist or it is still opened: unable to return meaningful level value.");
182 return (-1);
183 }
184 const char* symname = GetSymName();
185 const char* path;
186 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
187 if(pne){
188 path = pne->GetTitle();
189 }else{
190 path = symname;
191 }
192
193 TString path_str = path;
194 if(path_str[0]!='/') path_str.Prepend('/');
195 return path_str.CountChar('/');
4b94e753 196}
197
198//_____________________________________________________________________________
199Int_t AliAlignObj::Compare(const TObject *obj) const
200{
201 // Compare the levels of two
202 // alignment objects
203 // Used in the sorting during
204 // the application of alignment
205 // objects to the geometry
7e154d52 206 //
4b94e753 207 Int_t level = GetLevel();
208 Int_t level2 = ((AliAlignObj *)obj)->GetLevel();
209 if (level == level2)
210 return 0;
211 else
212 return ((level > level2) ? 1 : -1);
213}
214
c18195b9 215//_____________________________________________________________________________
216void AliAlignObj::AnglesToMatrix(const Double_t *angles, Double_t *rot) const
217{
fdf65bb5 218 // Calculates the rotation matrix using the
219 // Euler angles in "x y z" notation
7e154d52 220 //
c18195b9 221 Double_t degrad = TMath::DegToRad();
222 Double_t sinpsi = TMath::Sin(degrad*angles[0]);
223 Double_t cospsi = TMath::Cos(degrad*angles[0]);
224 Double_t sinthe = TMath::Sin(degrad*angles[1]);
225 Double_t costhe = TMath::Cos(degrad*angles[1]);
226 Double_t sinphi = TMath::Sin(degrad*angles[2]);
227 Double_t cosphi = TMath::Cos(degrad*angles[2]);
228
229 rot[0] = costhe*cosphi;
230 rot[1] = -costhe*sinphi;
231 rot[2] = sinthe;
232 rot[3] = sinpsi*sinthe*cosphi + cospsi*sinphi;
233 rot[4] = -sinpsi*sinthe*sinphi + cospsi*cosphi;
234 rot[5] = -costhe*sinpsi;
235 rot[6] = -cospsi*sinthe*cosphi + sinpsi*sinphi;
236 rot[7] = cospsi*sinthe*sinphi + sinpsi*cosphi;
237 rot[8] = costhe*cospsi;
238}
239
240//_____________________________________________________________________________
241Bool_t AliAlignObj::MatrixToAngles(const Double_t *rot, Double_t *angles) const
242{
fdf65bb5 243 // Calculates the Euler angles in "x y z" notation
244 // using the rotation matrix
b760c02e 245 // Returns false in case the rotation angles can not be
246 // extracted from the matrix
7e154d52 247 //
b760c02e 248 if(TMath::Abs(rot[0])<1e-7 || TMath::Abs(rot[8])<1e-7) {
249 AliError("Failed to extract roll-pitch-yall angles!");
250 return kFALSE;
251 }
c18195b9 252 Double_t raddeg = TMath::RadToDeg();
253 angles[0]=raddeg*TMath::ATan2(-rot[5],rot[8]);
254 angles[1]=raddeg*TMath::ASin(rot[2]);
255 angles[2]=raddeg*TMath::ATan2(-rot[1],rot[0]);
256 return kTRUE;
257}
258
03b18860 259//______________________________________________________________________________
260void AliAlignObj::Transform(AliTrackPoint &p) const
261{
262 // The method transforms the space-point coordinates using the
263 // transformation matrix provided by the AliAlignObj
264 // The covariance matrix is not affected since we assume
265 // that the transformations are sufficiently small
7e154d52 266 //
03b18860 267 if (fVolUID != p.GetVolumeID())
268 AliWarning(Form("Alignment object ID is not equal to the space-point ID (%d != %d)",fVolUID,p.GetVolumeID()));
269
270 TGeoHMatrix m;
271 GetMatrix(m);
272 Double_t *rot = m.GetRotationMatrix();
273 Double_t *tr = m.GetTranslation();
274
275 Float_t xyzin[3],xyzout[3];
276 p.GetXYZ(xyzin);
277 for (Int_t i = 0; i < 3; i++)
278 xyzout[i] = tr[i]+
279 xyzin[0]*rot[3*i]+
280 xyzin[1]*rot[3*i+1]+
281 xyzin[2]*rot[3*i+2];
282 p.SetXYZ(xyzout);
283
284}
285
79e21da6 286//_____________________________________________________________________________
03b18860 287void AliAlignObj::Transform(AliTrackPointArray &array) const
288{
e1e6896f 289 // This method is used to transform all the track points
290 // from the input AliTrackPointArray
7e154d52 291 //
03b18860 292 AliTrackPoint p;
293 for (Int_t i = 0; i < array.GetNPoints(); i++) {
294 array.GetPoint(p,i);
295 Transform(p);
296 array.AddPoint(i,&p);
297 }
298}
299
c18195b9 300//_____________________________________________________________________________
301void AliAlignObj::Print(Option_t *) const
302{
303 // Print the contents of the
304 // alignment object in angles and
305 // matrix representations
7e154d52 306 //
c18195b9 307 Double_t tr[3];
308 GetTranslation(tr);
309 Double_t angles[3];
310 GetAngles(angles);
311 TGeoHMatrix m;
312 GetMatrix(m);
313 const Double_t *rot = m.GetRotationMatrix();
c18195b9 314
b760c02e 315 printf("Volume=%s\n",GetSymName());
c041444f 316 if (GetVolUID() != 0) {
317 ELayerID layerId;
318 Int_t modId;
319 GetVolUID(layerId,modId);
320 printf("VolumeID=%d LayerID=%d ( %s ) ModuleID=%d\n", GetVolUID(),layerId,LayerName(layerId),modId);
321 }
322 printf("%12.8f%12.8f%12.8f Tx = %12.8f Psi = %12.8f\n", rot[0], rot[1], rot[2], tr[0], angles[0]);
323 printf("%12.8f%12.8f%12.8f Ty = %12.8f Theta = %12.8f\n", rot[3], rot[4], rot[5], tr[1], angles[1]);
324 printf("%12.8f%12.8f%12.8f Tz = %12.8f Phi = %12.8f\n", rot[6], rot[7], rot[8], tr[2], angles[2]);
325
326}
327
328//_____________________________________________________________________________
329Int_t AliAlignObj::LayerSize(Int_t layerId)
330{
7e154d52 331 // Get the layer size for layer corresponding to layerId.
f4b3bbb7 332 // Implemented only for ITS,TPC,TRD,TOF and HMPID
7e154d52 333 //
c041444f 334 if (layerId < kFirstLayer || layerId >= kLastLayer) {
335 AliErrorClass(Form("Invalid layer index %d ! Layer range is (%d -> %d) !",layerId,kFirstLayer,kLastLayer));
336 return 0;
337 }
338 else {
339 return fgLayerSize[layerId - kFirstLayer];
340 }
341}
342
343//_____________________________________________________________________________
344const char* AliAlignObj::LayerName(Int_t layerId)
345{
7e154d52 346 // Get the layer name corresponding to layerId.
f4b3bbb7 347 // Implemented only for ITS,TPC,TRD,TOF and HMPID
7e154d52 348 //
c041444f 349 if (layerId < kFirstLayer || layerId >= kLastLayer) {
350 AliErrorClass(Form("Invalid layer index %d ! Layer range is (%d -> %d) !",layerId,kFirstLayer,kLastLayer));
351 return "Invalid Layer!";
352 }
353 else {
354 return fgLayerName[layerId - kFirstLayer];
355 }
c18195b9 356}
357
c18195b9 358//_____________________________________________________________________________
befe2c08 359UShort_t AliAlignObj::LayerToVolUID(ELayerID layerId, Int_t modId)
c18195b9 360{
7e154d52 361 // From detector (layer) name and module number (according to detector
362 // internal numbering) build the unique numerical identity of that volume
363 // inside ALICE
befe2c08 364 // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
365 // remaining 11 for module ID inside det (2048 possible values).
c18195b9 366 //
befe2c08 367 return ((UShort_t(layerId) << 11) | UShort_t(modId));
c18195b9 368}
369
46ae650f 370//_____________________________________________________________________________
371UShort_t AliAlignObj::LayerToVolUID(Int_t layerId, Int_t modId)
372{
7e154d52 373 // From detector (layer) name and module number (according to detector
374 // internal numbering) build the unique numerical identity of that volume
375 // inside ALICE
46ae650f 376 // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
377 // remaining 11 for module ID inside det (2048 possible values).
378 //
379 return ((UShort_t(layerId) << 11) | UShort_t(modId));
380}
381
c18195b9 382//_____________________________________________________________________________
befe2c08 383AliAlignObj::ELayerID AliAlignObj::VolUIDToLayer(UShort_t voluid, Int_t &modId)
c18195b9 384{
7e154d52 385 // From voluid, unique numerical identity of that volume inside ALICE,
386 // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
387 // remaining 11 for module ID inside det (2048 possible values)), return
388 // the identity of the layer to which that volume belongs and sets the
389 // argument modId to the identity of that volume internally to the layer.
befe2c08 390 //
391 modId = voluid & 0x7ff;
c18195b9 392
befe2c08 393 return VolUIDToLayer(voluid);
c18195b9 394}
395
396//_____________________________________________________________________________
befe2c08 397AliAlignObj::ELayerID AliAlignObj::VolUIDToLayer(UShort_t voluid)
c18195b9 398{
7e154d52 399 // From voluid, unique numerical identity of that volume inside ALICE,
400 // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
401 // remaining 11 for module ID inside det (2048 possible values)), return
402 // the identity of the layer to which that volume belongs
befe2c08 403 //
404 return ELayerID((voluid >> 11) & 0x1f);
c18195b9 405}
03b18860 406
b760c02e 407//_____________________________________________________________________________
408void AliAlignObj::SetPars(Double_t x, Double_t y, Double_t z,
409 Double_t psi, Double_t theta, Double_t phi)
410{
7e154d52 411 // Set rotation matrix and translation using 3 angles and 3 translations
412 // The three angles are expressed in degrees
413 //
b760c02e 414 SetTranslation(x,y,z);
415 SetRotation(psi,theta,phi);
416}
417
1bfe7ffc 418//_____________________________________________________________________________
419Bool_t AliAlignObj::SetLocalPars(Double_t x, Double_t y, Double_t z,
420 Double_t psi, Double_t theta, Double_t phi)
421{
7e154d52 422 // Set the translations and angles (in degrees) by considering the
423 // parameters passed as arguments as expressed in the local reference
424 // system of the alignable volume (known by TGeo geometry).
425 // In case that the TGeo was not initialized or not closed,
426 // returns false and the object parameters are not set.
427 //
b760c02e 428 TGeoHMatrix m;
429 Double_t tr[3] = {x, y, z};
430 m.SetTranslation(tr);
431 Double_t angles[3] = {psi, theta, phi};
432 Double_t rot[9];
433 AnglesToMatrix(angles,rot);
434 m.SetRotation(rot);
435
436 return SetLocalMatrix(m);
437
438}
439
440//_____________________________________________________________________________
441Bool_t AliAlignObj::SetLocalMatrix(const TGeoMatrix& m)
442{
7e154d52 443 // Set the translations and angles by considering the TGeo matrix
444 // passed as argument as expressing the transformation in the local
445 // reference system of the alignable volume (known by TGeo geometry).
446 // In case that the TGeo was not initialized or not closed,
447 // returns false and the object parameters are not set.
448 //
1bfe7ffc 449 if (!gGeoManager || !gGeoManager->IsClosed()) {
450 AliError("Can't set the alignment object parameters! gGeoManager doesn't exist or it is still opened!");
451 return kFALSE;
452 }
453
b760c02e 454 const char* symname = GetSymName();
455 TGeoPhysicalNode* node;
456 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
457 if(pne){
458 node = gGeoManager->MakeAlignablePN(pne);
459 }else{
460 AliWarning(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as volume path!",symname));
461 node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(symname);
462 }
463
1bfe7ffc 464 if (!node) {
b760c02e 465 AliError(Form("Volume name or path %s not valid!",symname));
1bfe7ffc 466 return kFALSE;
467 }
468 if (node->IsAligned())
b760c02e 469 AliWarning(Form("Volume %s has been already misaligned!",symname));
1bfe7ffc 470
b760c02e 471 TGeoHMatrix m1;
472 const Double_t *tr = m.GetTranslation();
473 m1.SetTranslation(tr);
474 const Double_t* rot = m.GetRotationMatrix();
475 m1.SetRotation(rot);
1bfe7ffc 476
477 TGeoHMatrix align,gprime,gprimeinv;
478 gprime = *node->GetMatrix();
479 gprimeinv = gprime.Inverse();
b760c02e 480 m1.Multiply(&gprimeinv);
481 m1.MultiplyLeft(&gprime);
1bfe7ffc 482
b760c02e 483 return SetMatrix(m1);
484}
1bfe7ffc 485
b760c02e 486//_____________________________________________________________________________
487Bool_t AliAlignObj::SetMatrix(const TGeoMatrix& m)
488{
7e154d52 489 // Set rotation matrix and translation using the TGeoMatrix passed
490 // as argument considering it as relative to the global reference
491 // system
492 //
b760c02e 493 SetTranslation(m);
494 return SetRotation(m);
1bfe7ffc 495}
496
995ad051 497//_____________________________________________________________________________
498Bool_t AliAlignObj::ApplyToGeometry()
499{
7e154d52 500 // Apply the current alignment object to the TGeo geometry
501 // This method returns FALSE if the symname of the object was not
502 // valid neither to get a TGeoPEntry nor as a volume path
503 //
995ad051 504 if (!gGeoManager || !gGeoManager->IsClosed()) {
505 AliError("Can't apply the alignment object! gGeoManager doesn't exist or it is still opened!");
506 return kFALSE;
507 }
508
b760c02e 509 const char* symname = GetSymName();
510 const char* path;
511 TGeoPhysicalNode* node;
512 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
513 if(pne){
b760c02e 514 path = pne->GetTitle();
7e154d52 515 if(!gGeoManager->CheckPath(path)){
516 AliDebug(1,Form("Valid PNEntry but invalid volume path %s!",path));
517 // this should happen only for volumes in disactivated branches
518 return kTRUE;
519 }
520 node = gGeoManager->MakeAlignablePN(pne);
b760c02e 521 }else{
522 AliWarning(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
523 path=symname;
7e154d52 524 if (!gGeoManager->CheckPath(path)) {
525 AliError(Form("Volume path %s not valid!",path));
b760c02e 526 return kFALSE;
527 }
7e154d52 528 if (gGeoManager->GetListOfPhysicalNodes()->FindObject(path)) {
529 AliError(Form("Volume %s has already been misaligned!",path));
b760c02e 530 return kFALSE;
531 }
532 node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(path);
995ad051 533 }
48cac49d 534
48cac49d 535 if (!node) {
b760c02e 536 AliError(Form("Volume path %s not valid!",path));
995ad051 537 return kFALSE;
538 }
539
540 TGeoHMatrix align,gprime;
541 gprime = *node->GetMatrix();
542 GetMatrix(align);
543 gprime.MultiplyLeft(&align);
544 TGeoHMatrix *ginv = new TGeoHMatrix;
545 TGeoHMatrix *g = node->GetMatrix(node->GetLevel()-1);
546 *ginv = g->Inverse();
547 *ginv *= gprime;
b760c02e 548 AliAlignObj::ELayerID layerId; // unique identity for layer in the alobj
549 Int_t modId; // unique identity for volume inside layer in the alobj
995ad051 550 GetVolUID(layerId, modId);
b760c02e 551 AliDebug(2,Form("Aligning volume %s of detector layer %d with local ID %d",symname,layerId,modId));
995ad051 552 node->Align(ginv);
553
554 return kTRUE;
555}
556
557//_____________________________________________________________________________
b760c02e 558Bool_t AliAlignObj::GetFromGeometry(const char *symname, AliAlignObj &alobj)
995ad051 559{
b760c02e 560 // Get the alignment object which corresponds to the symbolic volume name
561 // symname (in case equal to the TGeo volume path)
562 // The method is extremely slow due to the searching by string.
563 // Therefore it should be used with great care!!
7e154d52 564 // This method returns FALSE if the symname of the object was not
565 // valid neither to get a TGeoPEntry nor as a volume path, or if the path
566 // associated to the TGeoPNEntry was not valid.
b760c02e 567 //
995ad051 568
569 // Reset the alignment object
570 alobj.SetPars(0,0,0,0,0,0);
b760c02e 571 alobj.SetSymName(symname);
995ad051 572
573 if (!gGeoManager || !gGeoManager->IsClosed()) {
574 AliErrorClass("Can't get the alignment object! gGeoManager doesn't exist or it is still opened!");
575 return kFALSE;
576 }
577
578 if (!gGeoManager->GetListOfPhysicalNodes()) {
579 AliErrorClass("Can't get the alignment object! gGeoManager doesn't contain any aligned nodes!");
580 return kFALSE;
581 }
582
b760c02e 583 const char *path;
584 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
585 if(pne){
586 path = pne->GetTitle();
587 }else{
588 AliWarningClass(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
589 path = symname;
590 }
995ad051 591 TObjArray* nodesArr = gGeoManager->GetListOfPhysicalNodes();
592 TGeoPhysicalNode* node = NULL;
593 for (Int_t iNode = 0; iNode < nodesArr->GetEntriesFast(); iNode++) {
b760c02e 594 TGeoPhysicalNode* tempNode = (TGeoPhysicalNode*) nodesArr->UncheckedAt(iNode);
595 const char *nodePath = tempNode->GetName();
596 if (strcmp(symname,nodePath) == 0) {
597 node = tempNode;
598 break;
599 }
995ad051 600 }
b760c02e 601
995ad051 602 if (!node) {
b760c02e 603 if (!gGeoManager->cd(symname)) {
604 AliErrorClass(Form("%s not valid neither as symbolic volume name nor as volume path!",symname));
e1c4b551 605 return kFALSE;
606 }
607 else {
b760c02e 608 AliWarningClass(Form("Volume (%s) has not been misaligned!",symname));
e1c4b551 609 return kTRUE;
610 }
995ad051 611 }
612
613 TGeoHMatrix align,gprime,g,ginv,l;
614 gprime = *node->GetMatrix();
615 l = *node->GetOriginalMatrix();
616 g = *node->GetMatrix(node->GetLevel()-1);
617 g *= l;
618 ginv = g.Inverse();
619 align = gprime * ginv;
995ad051 620
b760c02e 621 return alobj.SetMatrix(align);
995ad051 622}
623
79e21da6 624//_____________________________________________________________________________
c5304981 625void AliAlignObj::InitAlignObjFromGeometry()
626{
627 // Loop over all alignable volumes and extract
628 // the corresponding alignment objects from
629 // the TGeo geometry
25b4e81e 630
631 if(fgAlignObjs[0]) return;
c5304981 632
b760c02e 633 InitSymNames();
c5304981 634
c041444f 635 for (Int_t iLayer = kFirstLayer; iLayer < AliAlignObj::kLastLayer; iLayer++) {
636 fgAlignObjs[iLayer-kFirstLayer] = new AliAlignObj*[AliAlignObj::LayerSize(iLayer)];
c5304981 637 for (Int_t iModule = 0; iModule < AliAlignObj::LayerSize(iLayer); iModule++) {
c041444f 638 UShort_t volid = AliAlignObj::LayerToVolUID(iLayer,iModule);
b760c02e 639 fgAlignObjs[iLayer-kFirstLayer][iModule] = new AliAlignObjAngles("",volid,0,0,0,0,0,0,kTRUE);
640 const char *symname = SymName(volid);
641 if (!GetFromGeometry(symname, *fgAlignObjs[iLayer-kFirstLayer][iModule]))
642 AliErrorClass(Form("Failed to extract the alignment object for the volume (ID=%d and path=%s) !",volid,symname));
c5304981 643 }
644 }
645
646}
647
e1e6896f 648//_____________________________________________________________________________
649AliAlignObj* AliAlignObj::GetAlignObj(UShort_t voluid) {
650 // Returns the alignment object for given volume ID
7e154d52 651 //
e1e6896f 652 Int_t modId;
653 ELayerID layerId = VolUIDToLayer(voluid,modId);
654 return GetAlignObj(layerId,modId);
655}
656
c5304981 657//_____________________________________________________________________________
658AliAlignObj* AliAlignObj::GetAlignObj(ELayerID layerId, Int_t modId)
659{
7e154d52 660 // Returns pointer to alignment object given its layer and module ID
661 //
c5304981 662 if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
663 AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
664 return NULL;
665 }
b760c02e 666 InitAlignObjFromGeometry();
667
c5304981 668 return fgAlignObjs[layerId-kFirstLayer][modId];
669}
670
e1e6896f 671//_____________________________________________________________________________
b760c02e 672const char* AliAlignObj::SymName(UShort_t voluid) {
7e154d52 673 // Returns the symbolic volume name for given volume ID
674 //
e1e6896f 675 Int_t modId;
676 ELayerID layerId = VolUIDToLayer(voluid,modId);
b760c02e 677 return SymName(layerId,modId);
e1e6896f 678}
679
e7570944 680//_____________________________________________________________________________
b760c02e 681const char* AliAlignObj::SymName(ELayerID layerId, Int_t modId)
e7570944 682{
7e154d52 683 // Returns the symbolic volume name given for a given layer
684 // and module ID
685 //
e7570944 686 if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
687 AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
688 return NULL;
689 }
b760c02e 690 InitSymNames();
691
e7570944 692 return fgVolPath[layerId-kFirstLayer][modId].Data();
693}
694
03b18860 695//_____________________________________________________________________________
b760c02e 696void AliAlignObj::InitSymNames()
03b18860 697{
7e154d52 698 // Initialize the LUTs which associate the symbolic volume names
699 // for each alignable volume with their unique numerical identity.
700 // The LUTs are static, so they are created during the instantiation
701 // of the first intance of AliAlignObj
702 //
03b18860 703 if (fgVolPath[0]) return;
704
705 for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++)
7604a026 706 fgVolPath[iLayer] = new TString[fgLayerSize[iLayer]];
03b18860 707
7e154d52 708 TString symname;
709 Int_t modnum; // in the following, set it to 0 at the start of each layer
710
711 /********************* ITS layers ***********************/
712 TString strSPD = "ITS/SPD";
713 TString strSDD = "ITS/SDD";
714 TString strSSD = "ITS/SSD";
715 TString strStave = "/Stave";
716 TString strLadder = "/Ladder";
717 TString strSector = "/Sector";
718 TString strSensor = "/Sensor";
719 TString strEntryName1;
720 TString strEntryName2;
721
03b18860 722 /********************* SPD layer1 ***********************/
723 {
7e154d52 724 modnum = 0;
03b18860 725
726 for(Int_t c1 = 1; c1<=10; c1++){
7e154d52 727 strEntryName1 = strSPD;
728 strEntryName1 += 0;
729 strEntryName1 += strSector;
730 strEntryName1 += (c1-1);
03b18860 731 for(Int_t c2 =1; c2<=2; c2++){
7e154d52 732 strEntryName2 = strEntryName1;
733 strEntryName2 += strStave;
734 strEntryName2 += (c2-1);
03b18860 735 for(Int_t c3 =1; c3<=4; c3++){
7e154d52 736 symname = strEntryName2;
737 symname += strLadder;
738 symname += (c3-1);
739 fgVolPath[kSPD1-kFirstLayer][modnum] = symname.Data();
03b18860 740 modnum++;
741 }
742 }
743 }
744 }
745
746 /********************* SPD layer2 ***********************/
747 {
7e154d52 748 modnum = 0;
03b18860 749
750 for(Int_t c1 = 1; c1<=10; c1++){
7e154d52 751 strEntryName1 = strSPD;
752 strEntryName1 += 1;
753 strEntryName1 += strSector;
754 strEntryName1 += (c1-1);
03b18860 755 for(Int_t c2 =1; c2<=4; c2++){
7e154d52 756 strEntryName2 = strEntryName1;
757 strEntryName2 += strStave;
758 strEntryName2 += (c2-1);
03b18860 759 for(Int_t c3 =1; c3<=4; c3++){
7e154d52 760 symname = strEntryName2;
761 symname += strLadder;
762 symname += (c3-1);
763 fgVolPath[kSPD2-kFirstLayer][modnum] = symname.Data();
03b18860 764 modnum++;
765 }
766 }
767 }
768 }
769
770 /********************* SDD layer1 ***********************/
771 {
7e154d52 772 modnum=0;
03b18860 773
774 for(Int_t c1 = 1; c1<=14; c1++){
7e154d52 775 strEntryName1 = strSDD;
776 strEntryName1 += 2;
777 strEntryName1 +=strLadder;
778 strEntryName1 += (c1-1);
03b18860 779 for(Int_t c2 =1; c2<=6; c2++){
7e154d52 780 symname = strEntryName1;
781 symname += strSensor;
782 symname += (c2-1);
783 fgVolPath[kSDD1-kFirstLayer][modnum] = symname.Data();
03b18860 784 modnum++;
785 }
786 }
787 }
788
789 /********************* SDD layer2 ***********************/
790 {
7e154d52 791 modnum=0;
03b18860 792
793 for(Int_t c1 = 1; c1<=22; c1++){
7e154d52 794 strEntryName1 = strSDD;
795 strEntryName1 += 3;
796 strEntryName1 +=strLadder;
797 strEntryName1 += (c1-1);
03b18860 798 for(Int_t c2 = 1; c2<=8; c2++){
7e154d52 799 symname = strEntryName1;
800 symname += strSensor;
801 symname += (c2-1);
802 fgVolPath[kSDD2-kFirstLayer][modnum] = symname.Data();
03b18860 803 modnum++;
804 }
805 }
806 }
807
808 /********************* SSD layer1 ***********************/
809 {
7e154d52 810 modnum=0;
03b18860 811
812 for(Int_t c1 = 1; c1<=34; c1++){
7e154d52 813 strEntryName1 = strSSD;
814 strEntryName1 += 4;
815 strEntryName1 +=strLadder;
816 strEntryName1 += (c1-1);
03b18860 817 for(Int_t c2 = 1; c2<=22; c2++){
7e154d52 818 symname = strEntryName1;
819 symname += strSensor;
820 symname += (c2-1);
821 fgVolPath[kSSD1-kFirstLayer][modnum] = symname.Data();
03b18860 822 modnum++;
823 }
824 }
825 }
826
7e154d52 827 /********************* SSD layer2 ***********************/
03b18860 828 {
7e154d52 829 modnum=0;
03b18860 830
831 for(Int_t c1 = 1; c1<=38; c1++){
7e154d52 832 strEntryName1 = strSSD;
833 strEntryName1 += 5;
834 strEntryName1 +=strLadder;
835 strEntryName1 += (c1-1);
03b18860 836 for(Int_t c2 = 1; c2<=25; c2++){
7e154d52 837 symname = strEntryName1;
838 symname += strSensor;
839 symname += (c2-1);
840 fgVolPath[kSSD2-kFirstLayer][modnum] = symname.Data();
03b18860 841 modnum++;
842 }
843 }
844 }
845
7e154d52 846
847 /*************** TPC inner and outer layers ****************/
848 TString sAsector="TPC/EndcapA/Sector";
849 TString sCsector="TPC/EndcapC/Sector";
850 TString sInner="/InnerChamber";
851 TString sOuter="/OuterChamber";
852
e7570944 853 /*************** TPC inner chambers' layer ****************/
854 {
7e154d52 855 modnum = 0;
e7570944 856
857 for(Int_t cnt=1; cnt<=18; cnt++){
7e154d52 858 symname = sAsector;
b760c02e 859 symname += cnt;
7e154d52 860 symname += sInner;
b760c02e 861 fgVolPath[kTPC1-kFirstLayer][modnum] = symname.Data();
e7570944 862 modnum++;
863 }
864 for(Int_t cnt=1; cnt<=18; cnt++){
7e154d52 865 symname = sCsector;
b760c02e 866 symname += cnt;
7e154d52 867 symname += sInner;
b760c02e 868 fgVolPath[kTPC1-kFirstLayer][modnum] = symname.Data();
e7570944 869 modnum++;
870 }
871 }
872
873 /*************** TPC outer chambers' layer ****************/
874 {
7e154d52 875 modnum = 0;
e7570944 876
877 for(Int_t cnt=1; cnt<=18; cnt++){
7e154d52 878 symname = sAsector;
b760c02e 879 symname += cnt;
7e154d52 880 symname += sOuter;
b760c02e 881 fgVolPath[kTPC2-kFirstLayer][modnum] = symname.Data();
e7570944 882 modnum++;
883 }
884 for(Int_t cnt=1; cnt<=18; cnt++){
7e154d52 885 symname = sCsector;
b760c02e 886 symname += cnt;
7e154d52 887 symname += sOuter;
b760c02e 888 fgVolPath[kTPC2-kFirstLayer][modnum] = symname.Data();
e7570944 889 modnum++;
890 }
891 }
892
9abb5d7b 893 /********************* TOF layer ***********************/
894 {
7e154d52 895 modnum=0;
896
9abb5d7b 897 Int_t nstrA=15;
898 Int_t nstrB=19;
da027ef2 899 Int_t nstrC=19;
7e154d52 900 Int_t nSectors=18;
901 Int_t nStrips=nstrA+2*nstrB+2*nstrC;
902
903 TString snSM = "TOF/sm";
904 TString snSTRIP = "/strip";
905
906 for (Int_t isect = 0; isect < nSectors; isect++) {
907 for (Int_t istr = 1; istr <= nStrips; istr++) {
908 symname = snSM;
909 symname += Form("%02d",isect);
910 symname += snSTRIP;
911 symname += Form("%02d",istr);
912 fgVolPath[kTOF-kFirstLayer][modnum] = symname.Data();
913 modnum++;
914 }
9abb5d7b 915 }
916 }
c8874495 917
f4b3bbb7 918 /********************* HMPID layer ***********************/
c8874495 919 {
c1f4a635 920 TString str = "/HMPID/Chamber";
b760c02e 921 TString symname;
c8874495 922
7e154d52 923 for (modnum=0; modnum < 7; modnum++) {
b760c02e 924 symname = str;
c1f4a635 925 symname += modnum;
f4b3bbb7 926 fgVolPath[kHMPID-kFirstLayer][modnum] = symname.Data();
c8874495 927 }
928 }
274fcc1a 929
7e154d52 930 /********************* TRD layers 1-6 *******************/
931 //!! 6 layers with index increasing in outwards direction
274fcc1a 932 {
e1e6896f 933 Int_t arTRDlayId[6] = {kTRD1, kTRD2, kTRD3, kTRD4, kTRD5, kTRD6};
274fcc1a 934
7e154d52 935 TString snStr = "TRD/sm";
936 TString snApp1 = "/st";
937 TString snApp2 = "/pl";
938
a1a23a88 939 for(Int_t layer=0; layer<6; layer++){
7e154d52 940 modnum=0;
941 for (Int_t isect = 0; isect < 18; isect++) {
942 for (Int_t icham = 0; icham < 5; icham++) {
943 symname = snStr;
944 symname += Form("%02d",isect);
945 symname += snApp1;
946 symname += icham;
947 symname += snApp2;
948 symname += layer;
b760c02e 949 fgVolPath[arTRDlayId[layer]-kFirstLayer][modnum] = symname.Data();
274fcc1a 950 modnum++;
951 }
952 }
953 }
954 }
03b18860 955}
7e154d52 956