]> git.uio.no Git - u/mrichter/AliRoot.git/blame - STEER/AliAlignObj.cxx
Updated comments (Raffaele)
[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//-----------------------------------------------------------------
befe2c08 17// Implementation of the alignment object class through the abstract
18// class AliAlignObj. From it two derived concrete representation of
19// alignment object class (AliAlignObjAngles, AliAlignObjMatrix) are
20// 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 ??
03b18860 40 7, // RICH ??
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 "?","?",
03b18860 53 "RICH 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{
156 // From detector name and module number (according to detector numbering)
157 // build fVolUID, unique numerical identity of that volume inside ALICE
158 // fVolUID is 16 bits, first 5 reserved for detID (32 possible values),
159 // remaining 11 for module ID inside det (2048 possible values).
160 //
161 layerId = VolUIDToLayer(fVolUID,modId);
162}
163
b760c02e 164//_____________________________________________________________________________
165Bool_t AliAlignObj::GetPars(Double_t tr[], Double_t angles[]) const
166{
167 GetTranslation(tr);
168 return GetAngles(angles);
169}
170
4b94e753 171//_____________________________________________________________________________
172Int_t AliAlignObj::GetLevel() const
173{
85fbf070 174 // Return the geometry level of the alignable volume to which
175 // the alignment object is associated; this is the number of
176 // slashes in the corresponding volume path
177 //
178 if(!gGeoManager){
179 AliWarning("gGeoManager doesn't exist or it is still opened: unable to return meaningful level value.");
180 return (-1);
181 }
182 const char* symname = GetSymName();
183 const char* path;
184 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
185 if(pne){
186 path = pne->GetTitle();
187 }else{
188 path = symname;
189 }
190
191 TString path_str = path;
192 if(path_str[0]!='/') path_str.Prepend('/');
193 return path_str.CountChar('/');
4b94e753 194}
195
196//_____________________________________________________________________________
197Int_t AliAlignObj::Compare(const TObject *obj) const
198{
199 // Compare the levels of two
200 // alignment objects
201 // Used in the sorting during
202 // the application of alignment
203 // objects to the geometry
204 Int_t level = GetLevel();
205 Int_t level2 = ((AliAlignObj *)obj)->GetLevel();
206 if (level == level2)
207 return 0;
208 else
209 return ((level > level2) ? 1 : -1);
210}
211
c18195b9 212//_____________________________________________________________________________
213void AliAlignObj::AnglesToMatrix(const Double_t *angles, Double_t *rot) const
214{
fdf65bb5 215 // Calculates the rotation matrix using the
216 // Euler angles in "x y z" notation
c18195b9 217 Double_t degrad = TMath::DegToRad();
218 Double_t sinpsi = TMath::Sin(degrad*angles[0]);
219 Double_t cospsi = TMath::Cos(degrad*angles[0]);
220 Double_t sinthe = TMath::Sin(degrad*angles[1]);
221 Double_t costhe = TMath::Cos(degrad*angles[1]);
222 Double_t sinphi = TMath::Sin(degrad*angles[2]);
223 Double_t cosphi = TMath::Cos(degrad*angles[2]);
224
225 rot[0] = costhe*cosphi;
226 rot[1] = -costhe*sinphi;
227 rot[2] = sinthe;
228 rot[3] = sinpsi*sinthe*cosphi + cospsi*sinphi;
229 rot[4] = -sinpsi*sinthe*sinphi + cospsi*cosphi;
230 rot[5] = -costhe*sinpsi;
231 rot[6] = -cospsi*sinthe*cosphi + sinpsi*sinphi;
232 rot[7] = cospsi*sinthe*sinphi + sinpsi*cosphi;
233 rot[8] = costhe*cospsi;
234}
235
236//_____________________________________________________________________________
237Bool_t AliAlignObj::MatrixToAngles(const Double_t *rot, Double_t *angles) const
238{
fdf65bb5 239 // Calculates the Euler angles in "x y z" notation
240 // using the rotation matrix
b760c02e 241 // Returns false in case the rotation angles can not be
242 // extracted from the matrix
243 if(TMath::Abs(rot[0])<1e-7 || TMath::Abs(rot[8])<1e-7) {
244 AliError("Failed to extract roll-pitch-yall angles!");
245 return kFALSE;
246 }
c18195b9 247 Double_t raddeg = TMath::RadToDeg();
248 angles[0]=raddeg*TMath::ATan2(-rot[5],rot[8]);
249 angles[1]=raddeg*TMath::ASin(rot[2]);
250 angles[2]=raddeg*TMath::ATan2(-rot[1],rot[0]);
251 return kTRUE;
252}
253
03b18860 254//______________________________________________________________________________
255void AliAlignObj::Transform(AliTrackPoint &p) const
256{
257 // The method transforms the space-point coordinates using the
258 // transformation matrix provided by the AliAlignObj
259 // The covariance matrix is not affected since we assume
260 // that the transformations are sufficiently small
261
262 if (fVolUID != p.GetVolumeID())
263 AliWarning(Form("Alignment object ID is not equal to the space-point ID (%d != %d)",fVolUID,p.GetVolumeID()));
264
265 TGeoHMatrix m;
266 GetMatrix(m);
267 Double_t *rot = m.GetRotationMatrix();
268 Double_t *tr = m.GetTranslation();
269
270 Float_t xyzin[3],xyzout[3];
271 p.GetXYZ(xyzin);
272 for (Int_t i = 0; i < 3; i++)
273 xyzout[i] = tr[i]+
274 xyzin[0]*rot[3*i]+
275 xyzin[1]*rot[3*i+1]+
276 xyzin[2]*rot[3*i+2];
277 p.SetXYZ(xyzout);
278
279}
280
79e21da6 281//_____________________________________________________________________________
03b18860 282void AliAlignObj::Transform(AliTrackPointArray &array) const
283{
e1e6896f 284 // This method is used to transform all the track points
285 // from the input AliTrackPointArray
03b18860 286 AliTrackPoint p;
287 for (Int_t i = 0; i < array.GetNPoints(); i++) {
288 array.GetPoint(p,i);
289 Transform(p);
290 array.AddPoint(i,&p);
291 }
292}
293
c18195b9 294//_____________________________________________________________________________
295void AliAlignObj::Print(Option_t *) const
296{
297 // Print the contents of the
298 // alignment object in angles and
299 // matrix representations
300 Double_t tr[3];
301 GetTranslation(tr);
302 Double_t angles[3];
303 GetAngles(angles);
304 TGeoHMatrix m;
305 GetMatrix(m);
306 const Double_t *rot = m.GetRotationMatrix();
c18195b9 307
b760c02e 308 printf("Volume=%s\n",GetSymName());
c041444f 309 if (GetVolUID() != 0) {
310 ELayerID layerId;
311 Int_t modId;
312 GetVolUID(layerId,modId);
313 printf("VolumeID=%d LayerID=%d ( %s ) ModuleID=%d\n", GetVolUID(),layerId,LayerName(layerId),modId);
314 }
315 printf("%12.8f%12.8f%12.8f Tx = %12.8f Psi = %12.8f\n", rot[0], rot[1], rot[2], tr[0], angles[0]);
316 printf("%12.8f%12.8f%12.8f Ty = %12.8f Theta = %12.8f\n", rot[3], rot[4], rot[5], tr[1], angles[1]);
317 printf("%12.8f%12.8f%12.8f Tz = %12.8f Phi = %12.8f\n", rot[6], rot[7], rot[8], tr[2], angles[2]);
318
319}
320
321//_____________________________________________________________________________
322Int_t AliAlignObj::LayerSize(Int_t layerId)
323{
324 // Get the corresponding layer size.
325 // Implemented only for ITS,TPC,TRD,TOF and RICH
326 if (layerId < kFirstLayer || layerId >= kLastLayer) {
327 AliErrorClass(Form("Invalid layer index %d ! Layer range is (%d -> %d) !",layerId,kFirstLayer,kLastLayer));
328 return 0;
329 }
330 else {
331 return fgLayerSize[layerId - kFirstLayer];
332 }
333}
334
335//_____________________________________________________________________________
336const char* AliAlignObj::LayerName(Int_t layerId)
337{
338 // Get the corresponding layer name.
339 // Implemented only for ITS,TPC,TRD,TOF and RICH
340 if (layerId < kFirstLayer || layerId >= kLastLayer) {
341 AliErrorClass(Form("Invalid layer index %d ! Layer range is (%d -> %d) !",layerId,kFirstLayer,kLastLayer));
342 return "Invalid Layer!";
343 }
344 else {
345 return fgLayerName[layerId - kFirstLayer];
346 }
c18195b9 347}
348
c18195b9 349//_____________________________________________________________________________
befe2c08 350UShort_t AliAlignObj::LayerToVolUID(ELayerID layerId, Int_t modId)
c18195b9 351{
befe2c08 352 // From detector (layer) name and module number (according to detector numbering)
353 // build fVolUID, unique numerical identity of that volume inside ALICE
354 // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
355 // remaining 11 for module ID inside det (2048 possible values).
c18195b9 356 //
befe2c08 357 return ((UShort_t(layerId) << 11) | UShort_t(modId));
c18195b9 358}
359
46ae650f 360//_____________________________________________________________________________
361UShort_t AliAlignObj::LayerToVolUID(Int_t layerId, Int_t modId)
362{
363 // From detector (layer) index and module number (according to detector numbering)
364 // build fVolUID, unique numerical identity of that volume inside ALICE
365 // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
366 // remaining 11 for module ID inside det (2048 possible values).
367 //
368 return ((UShort_t(layerId) << 11) | UShort_t(modId));
369}
370
c18195b9 371//_____________________________________________________________________________
befe2c08 372AliAlignObj::ELayerID AliAlignObj::VolUIDToLayer(UShort_t voluid, Int_t &modId)
c18195b9 373{
befe2c08 374 // From detector (layer) name and module number (according to detector numbering)
375 // build fVolUID, unique numerical identity of that volume inside ALICE
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 modId = voluid & 0x7ff;
c18195b9 380
befe2c08 381 return VolUIDToLayer(voluid);
c18195b9 382}
383
384//_____________________________________________________________________________
befe2c08 385AliAlignObj::ELayerID AliAlignObj::VolUIDToLayer(UShort_t voluid)
c18195b9 386{
befe2c08 387 // From detector (layer) name and module number (according to detector numbering)
388 // build fVolUID, unique numerical identity of that volume inside ALICE
389 // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
390 // remaining 11 for module ID inside det (2048 possible values).
391 //
392 return ELayerID((voluid >> 11) & 0x1f);
c18195b9 393}
03b18860 394
b760c02e 395//_____________________________________________________________________________
396void AliAlignObj::SetPars(Double_t x, Double_t y, Double_t z,
397 Double_t psi, Double_t theta, Double_t phi)
398{
399 // Set rotation matrix and translation
400 // using 3 angles and 3 translations
401 SetTranslation(x,y,z);
402 SetRotation(psi,theta,phi);
403}
404
1bfe7ffc 405//_____________________________________________________________________________
406Bool_t AliAlignObj::SetLocalPars(Double_t x, Double_t y, Double_t z,
407 Double_t psi, Double_t theta, Double_t phi)
408{
409 // Set the translations and angles by using parameters
410 // defined in the local (in TGeo means) coordinate system
411 // of the alignable volume. In case that the TGeo was
412 // initialized, returns false and the object parameters are
413 // not set.
b760c02e 414 TGeoHMatrix m;
415 Double_t tr[3] = {x, y, z};
416 m.SetTranslation(tr);
417 Double_t angles[3] = {psi, theta, phi};
418 Double_t rot[9];
419 AnglesToMatrix(angles,rot);
420 m.SetRotation(rot);
421
422 return SetLocalMatrix(m);
423
424}
425
426//_____________________________________________________________________________
427Bool_t AliAlignObj::SetLocalMatrix(const TGeoMatrix& m)
428{
429 // Set the translations and angles by using TGeo matrix
430 // defined in the local (in TGeo means) coordinate system
431 // of the alignable volume. In case that the TGeo was
432 // initialized, returns false and the object parameters are
433 // not set.
434
1bfe7ffc 435 if (!gGeoManager || !gGeoManager->IsClosed()) {
436 AliError("Can't set the alignment object parameters! gGeoManager doesn't exist or it is still opened!");
437 return kFALSE;
438 }
439
b760c02e 440 const char* symname = GetSymName();
441 TGeoPhysicalNode* node;
442 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
443 if(pne){
444 node = gGeoManager->MakeAlignablePN(pne);
445 }else{
446 AliWarning(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as volume path!",symname));
447 node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(symname);
448 }
449
1bfe7ffc 450 if (!node) {
b760c02e 451 AliError(Form("Volume name or path %s not valid!",symname));
1bfe7ffc 452 return kFALSE;
453 }
454 if (node->IsAligned())
b760c02e 455 AliWarning(Form("Volume %s has been already misaligned!",symname));
1bfe7ffc 456
b760c02e 457 TGeoHMatrix m1;
458 const Double_t *tr = m.GetTranslation();
459 m1.SetTranslation(tr);
460 const Double_t* rot = m.GetRotationMatrix();
461 m1.SetRotation(rot);
1bfe7ffc 462
463 TGeoHMatrix align,gprime,gprimeinv;
464 gprime = *node->GetMatrix();
465 gprimeinv = gprime.Inverse();
b760c02e 466 m1.Multiply(&gprimeinv);
467 m1.MultiplyLeft(&gprime);
1bfe7ffc 468
b760c02e 469 return SetMatrix(m1);
470}
1bfe7ffc 471
b760c02e 472//_____________________________________________________________________________
473Bool_t AliAlignObj::SetMatrix(const TGeoMatrix& m)
474{
475 // Set rotation matrix and translation
476 // using TGeoMatrix
477 SetTranslation(m);
478 return SetRotation(m);
1bfe7ffc 479}
480
995ad051 481//_____________________________________________________________________________
482Bool_t AliAlignObj::ApplyToGeometry()
483{
484 // Apply the current alignment object
485 // to the TGeo geometry
486
487 if (!gGeoManager || !gGeoManager->IsClosed()) {
488 AliError("Can't apply the alignment object! gGeoManager doesn't exist or it is still opened!");
489 return kFALSE;
490 }
491
b760c02e 492 const char* symname = GetSymName();
493 const char* path;
494 TGeoPhysicalNode* node;
495 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
496 if(pne){
497 node = gGeoManager->MakeAlignablePN(pne);
498 if(!node) return kFALSE;
499 path = pne->GetTitle();
500 }else{
501 AliWarning(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
502 path=symname;
503 if (gGeoManager->GetListOfPhysicalNodes()->FindObject(path)) {
504 AliError(Form("Volume %s has already been misaligned!",path));
505 return kFALSE;
506 }
507 if (!gGeoManager->cd(path)) {
508 AliError(Form("Volume path %s not valid!",path));
509 return kFALSE;
510 }
511 node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(path);
995ad051 512 }
48cac49d 513
48cac49d 514 if (!node) {
b760c02e 515 AliError(Form("Volume path %s not valid!",path));
995ad051 516 return kFALSE;
517 }
518
519 TGeoHMatrix align,gprime;
520 gprime = *node->GetMatrix();
521 GetMatrix(align);
522 gprime.MultiplyLeft(&align);
523 TGeoHMatrix *ginv = new TGeoHMatrix;
524 TGeoHMatrix *g = node->GetMatrix(node->GetLevel()-1);
525 *ginv = g->Inverse();
526 *ginv *= gprime;
b760c02e 527 AliAlignObj::ELayerID layerId; // unique identity for layer in the alobj
528 Int_t modId; // unique identity for volume inside layer in the alobj
995ad051 529 GetVolUID(layerId, modId);
b760c02e 530 AliDebug(2,Form("Aligning volume %s of detector layer %d with local ID %d",symname,layerId,modId));
995ad051 531 node->Align(ginv);
532
533 return kTRUE;
534}
535
536//_____________________________________________________________________________
b760c02e 537Bool_t AliAlignObj::GetFromGeometry(const char *symname, AliAlignObj &alobj)
995ad051 538{
b760c02e 539 // Get the alignment object which corresponds to the symbolic volume name
540 // symname (in case equal to the TGeo volume path)
541 // The method is extremely slow due to the searching by string.
542 // Therefore it should be used with great care!!
543 //
995ad051 544
545 // Reset the alignment object
546 alobj.SetPars(0,0,0,0,0,0);
b760c02e 547 alobj.SetSymName(symname);
995ad051 548
549 if (!gGeoManager || !gGeoManager->IsClosed()) {
550 AliErrorClass("Can't get the alignment object! gGeoManager doesn't exist or it is still opened!");
551 return kFALSE;
552 }
553
554 if (!gGeoManager->GetListOfPhysicalNodes()) {
555 AliErrorClass("Can't get the alignment object! gGeoManager doesn't contain any aligned nodes!");
556 return kFALSE;
557 }
558
b760c02e 559 const char *path;
560 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
561 if(pne){
562 path = pne->GetTitle();
563 }else{
564 AliWarningClass(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
565 path = symname;
566 }
995ad051 567 TObjArray* nodesArr = gGeoManager->GetListOfPhysicalNodes();
568 TGeoPhysicalNode* node = NULL;
569 for (Int_t iNode = 0; iNode < nodesArr->GetEntriesFast(); iNode++) {
b760c02e 570 TGeoPhysicalNode* tempNode = (TGeoPhysicalNode*) nodesArr->UncheckedAt(iNode);
571 const char *nodePath = tempNode->GetName();
572 if (strcmp(symname,nodePath) == 0) {
573 node = tempNode;
574 break;
575 }
995ad051 576 }
b760c02e 577
995ad051 578 if (!node) {
b760c02e 579 if (!gGeoManager->cd(symname)) {
580 AliErrorClass(Form("%s not valid neither as symbolic volume name nor as volume path!",symname));
e1c4b551 581 return kFALSE;
582 }
583 else {
b760c02e 584 AliWarningClass(Form("Volume (%s) has not been misaligned!",symname));
e1c4b551 585 return kTRUE;
586 }
995ad051 587 }
588
589 TGeoHMatrix align,gprime,g,ginv,l;
590 gprime = *node->GetMatrix();
591 l = *node->GetOriginalMatrix();
592 g = *node->GetMatrix(node->GetLevel()-1);
593 g *= l;
594 ginv = g.Inverse();
595 align = gprime * ginv;
995ad051 596
b760c02e 597 return alobj.SetMatrix(align);
995ad051 598}
599
79e21da6 600//_____________________________________________________________________________
c5304981 601void AliAlignObj::InitAlignObjFromGeometry()
602{
603 // Loop over all alignable volumes and extract
604 // the corresponding alignment objects from
605 // the TGeo geometry
25b4e81e 606
607 if(fgAlignObjs[0]) return;
c5304981 608
b760c02e 609 InitSymNames();
c5304981 610
c041444f 611 for (Int_t iLayer = kFirstLayer; iLayer < AliAlignObj::kLastLayer; iLayer++) {
612 fgAlignObjs[iLayer-kFirstLayer] = new AliAlignObj*[AliAlignObj::LayerSize(iLayer)];
c5304981 613 for (Int_t iModule = 0; iModule < AliAlignObj::LayerSize(iLayer); iModule++) {
c041444f 614 UShort_t volid = AliAlignObj::LayerToVolUID(iLayer,iModule);
b760c02e 615 fgAlignObjs[iLayer-kFirstLayer][iModule] = new AliAlignObjAngles("",volid,0,0,0,0,0,0,kTRUE);
616 const char *symname = SymName(volid);
617 if (!GetFromGeometry(symname, *fgAlignObjs[iLayer-kFirstLayer][iModule]))
618 AliErrorClass(Form("Failed to extract the alignment object for the volume (ID=%d and path=%s) !",volid,symname));
c5304981 619 }
620 }
621
622}
623
e1e6896f 624//_____________________________________________________________________________
625AliAlignObj* AliAlignObj::GetAlignObj(UShort_t voluid) {
626 // Returns the alignment object for given volume ID
627 Int_t modId;
628 ELayerID layerId = VolUIDToLayer(voluid,modId);
629 return GetAlignObj(layerId,modId);
630}
631
c5304981 632//_____________________________________________________________________________
633AliAlignObj* AliAlignObj::GetAlignObj(ELayerID layerId, Int_t modId)
634{
e1e6896f 635 // Returns pointer to alignment object givent its layer and module ID
c5304981 636 if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
637 AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
638 return NULL;
639 }
b760c02e 640 InitAlignObjFromGeometry();
641
c5304981 642 return fgAlignObjs[layerId-kFirstLayer][modId];
643}
644
e1e6896f 645//_____________________________________________________________________________
b760c02e 646const char* AliAlignObj::SymName(UShort_t voluid) {
e1e6896f 647 // Returns the volume path for given volume ID
648 Int_t modId;
649 ELayerID layerId = VolUIDToLayer(voluid,modId);
b760c02e 650 return SymName(layerId,modId);
e1e6896f 651}
652
e7570944 653//_____________________________________________________________________________
b760c02e 654const char* AliAlignObj::SymName(ELayerID layerId, Int_t modId)
e7570944 655{
e1e6896f 656 // Returns volume path to alignment object givent its layer and module ID
e7570944 657 if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
658 AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
659 return NULL;
660 }
b760c02e 661 InitSymNames();
662
e7570944 663 return fgVolPath[layerId-kFirstLayer][modId].Data();
664}
665
03b18860 666//_____________________________________________________________________________
b760c02e 667void AliAlignObj::InitSymNames()
03b18860 668{
669 // Initialize the LUTs which contain
670 // the TGeo volume paths for each
671 // alignable volume. The LUTs are
672 // static, so they are created during
673 // the creation of the first intance
674 // of AliAlignObj
675
676 if (fgVolPath[0]) return;
677
678 for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++)
7604a026 679 fgVolPath[iLayer] = new TString[fgLayerSize[iLayer]];
03b18860 680
681 /********************* SPD layer1 ***********************/
682 {
683 Int_t modnum = 0;
684 TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT12_1/I12B_"; //".../I12A_"
685 TString str1 = "/I10B_"; //"/I10A_";
686 TString str2 = "/I107_"; //"/I103_"
995ad051 687 // TString str3 = "/I101_1/ITS1_1";
b760c02e 688 TString symname, symname1, symname2;
03b18860 689
690 for(Int_t c1 = 1; c1<=10; c1++){
b760c02e 691 symname = str0;
692 symname += c1;
693 symname += str1;
03b18860 694 for(Int_t c2 =1; c2<=2; c2++){
b760c02e 695 symname1 = symname;
696 symname1 += c2;
697 symname1 += str2;
03b18860 698 for(Int_t c3 =1; c3<=4; c3++){
b760c02e 699 symname2 = symname1;
700 symname2 += c3;
701 // symname2 += str3;
702 fgVolPath[kSPD1-kFirstLayer][modnum] = symname2.Data();
03b18860 703 modnum++;
704 }
705 }
706 }
707 }
708
709 /********************* SPD layer2 ***********************/
710 {
711 Int_t modnum = 0;
712 TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT12_1/I12B_"; //".../I12A_"
713 TString str1 = "/I20B_"; //"/I20A"
714 TString str2 = "/I1D7_"; //"/I1D3"
995ad051 715 // TString str3 = "/I1D1_1/ITS2_1";
b760c02e 716 TString symname, symname1, symname2;
03b18860 717
718 for(Int_t c1 = 1; c1<=10; c1++){
b760c02e 719 symname = str0;
720 symname += c1;
721 symname += str1;
03b18860 722 for(Int_t c2 =1; c2<=4; c2++){
b760c02e 723 symname1 = symname;
724 symname1 += c2;
725 symname1 += str2;
03b18860 726 for(Int_t c3 =1; c3<=4; c3++){
b760c02e 727 symname2 = symname1;
728 symname2 += c3;
729 // symname2 += str3;
730 fgVolPath[kSPD2-kFirstLayer][modnum] = symname2.Data();
03b18860 731 modnum++;
732 }
733 }
734 }
735 }
736
737 /********************* SDD layer1 ***********************/
738 {
739 Int_t modnum=0;
740 TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT34_1/I004_";
741 TString str1 = "/I302_";
995ad051 742 // TString str2 = "/ITS3_1";
b760c02e 743 TString symname, symname1;
03b18860 744
745 for(Int_t c1 = 1; c1<=14; c1++){
b760c02e 746 symname = str0;
747 symname += c1;
748 symname += str1;
03b18860 749 for(Int_t c2 =1; c2<=6; c2++){
b760c02e 750 symname1 = symname;
751 symname1 += c2;
752 // symname1 += str2;
753 fgVolPath[kSDD1-kFirstLayer][modnum] = symname1.Data();
03b18860 754 modnum++;
755 }
756 }
757 }
758
759 /********************* SDD layer2 ***********************/
760 {
761 Int_t modnum=0;
762 TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT34_1/I005_";
763 TString str1 = "/I402_";
995ad051 764 // TString str2 = "/ITS4_1";
b760c02e 765 TString symname, symname1;
03b18860 766
767 for(Int_t c1 = 1; c1<=22; c1++){
b760c02e 768 symname = str0;
769 symname += c1;
770 symname += str1;
03b18860 771 for(Int_t c2 = 1; c2<=8; c2++){
b760c02e 772 symname1 = symname;
773 symname1 += c2;
774 // symname1 += str2;
775 fgVolPath[kSDD2-kFirstLayer][modnum] = symname1.Data();
03b18860 776 modnum++;
777 }
778 }
779 }
780
781 /********************* SSD layer1 ***********************/
782 {
783 Int_t modnum=0;
784 TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT56_1/I565_";
785 TString str1 = "/I562_";
995ad051 786 // TString str2 = "/ITS5_1";
b760c02e 787 TString symname, symname1;
03b18860 788
789 for(Int_t c1 = 1; c1<=34; c1++){
b760c02e 790 symname = str0;
791 symname += c1;
792 symname += str1;
03b18860 793 for(Int_t c2 = 1; c2<=22; c2++){
b760c02e 794 symname1 = symname;
795 symname1 += c2;
796 // symname1 += str2;
797 fgVolPath[kSSD1-kFirstLayer][modnum] = symname1.Data();
03b18860 798 modnum++;
799 }
800 }
801 }
802
803 /********************* SSD layer1 ***********************/
804 {
805 Int_t modnum=0;
806 TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT56_1/I569_";
807 TString str1 = "/I566_";
995ad051 808 // TString str2 = "/ITS6_1";
b760c02e 809 TString symname, symname1;
03b18860 810
811 for(Int_t c1 = 1; c1<=38; c1++){
b760c02e 812 symname = str0;
813 symname += c1;
814 symname += str1;
03b18860 815 for(Int_t c2 = 1; c2<=25; c2++){
b760c02e 816 symname1 = symname;
817 symname1 += c2;
818 // symname1 += str2;
819 fgVolPath[kSSD2-kFirstLayer][modnum] = symname1.Data();
03b18860 820 modnum++;
821 }
822 }
823 }
824
e7570944 825 /*************** TPC inner chambers' layer ****************/
826 {
827 Int_t modnum = 0;
828 TString str1 = "ALIC_1/TPC_M_1/TPC_Drift_1/TPC_ENDCAP_1/TPC_SECT_";
829 TString str2 = "ALIC_1/TPC_M_1/TPC_Drift_1/TPC_ENDCAP_2/TPC_SECT_";
e1e6896f 830 TString strIn = "/TPC_IROC_1";
b760c02e 831 TString symname;
e7570944 832
833 for(Int_t cnt=1; cnt<=18; cnt++){
b760c02e 834 symname = str1;
835 symname += cnt;
836 symname += strIn;
837 fgVolPath[kTPC1-kFirstLayer][modnum] = symname.Data();
e7570944 838 modnum++;
839 }
840 for(Int_t cnt=1; cnt<=18; cnt++){
b760c02e 841 symname = str2;
842 symname += cnt;
843 symname += strIn;
844 fgVolPath[kTPC1-kFirstLayer][modnum] = symname.Data();
e7570944 845 modnum++;
846 }
847 }
848
849 /*************** TPC outer chambers' layer ****************/
850 {
851 Int_t modnum = 0;
852 TString str1 = "ALIC_1/TPC_M_1/TPC_Drift_1/TPC_ENDCAP_1/TPC_SECT_";
853 TString str2 = "ALIC_1/TPC_M_1/TPC_Drift_1/TPC_ENDCAP_2/TPC_SECT_";
e1e6896f 854 TString strOut = "/TPC_OROC_1";
b760c02e 855 TString symname;
e7570944 856
857 for(Int_t cnt=1; cnt<=18; cnt++){
b760c02e 858 symname = str1;
859 symname += cnt;
860 symname += strOut;
861 fgVolPath[kTPC2-kFirstLayer][modnum] = symname.Data();
e7570944 862 modnum++;
863 }
864 for(Int_t cnt=1; cnt<=18; cnt++){
b760c02e 865 symname = str2;
866 symname += cnt;
867 symname += strOut;
868 fgVolPath[kTPC2-kFirstLayer][modnum] = symname.Data();
e7570944 869 modnum++;
870 }
871 }
872
9abb5d7b 873 /********************* TOF layer ***********************/
874 {
875 Int_t nstrA=15;
876 Int_t nstrB=19;
da027ef2 877 Int_t nstrC=19;
878 Int_t nsec=18;
9abb5d7b 879 Int_t nStripSec=nstrA+2*nstrB+2*nstrC;
da027ef2 880 Int_t nStrip=nStripSec*nsec;
9abb5d7b 881
da027ef2 882 for (Int_t modnum=0; modnum < nStrip; modnum++) {
9abb5d7b 883
884 Int_t sector = modnum/nStripSec;
9abb5d7b 885 Char_t string1[100];
886 Char_t string2[100];
9abb5d7b 887 Int_t icopy=-1;
de0b6220 888 icopy=sector;
889
890 // Old 6h convention
891 // if(sector<13){
892 // icopy=sector+5;}
893 // else{ icopy=sector-13;}
38b3a170 894
06e24a91 895 sprintf(string1,"/ALIC_1/B077_1/BSEGMO%i_1/BTOF%i_1/FTOA_0/FLTA_0",sector,sector);
da027ef2 896
9abb5d7b 897 Int_t strInSec=modnum%nStripSec;
da027ef2 898 icopy= strInSec;
899 icopy++;
900 sprintf(string2,"FSTR_%i",icopy);
9abb5d7b 901 Char_t path[100];
902 sprintf(path,"%s/%s",string1,string2);
903 // printf("%d %s\n",modnum,path);
904 fgVolPath[kTOF-kFirstLayer][modnum] = path;
905 }
906 }
c8874495 907
908 /********************* RICH layer ***********************/
909 {
910 TString str = "ALIC_1/RICH_";
b760c02e 911 TString symname;
c8874495 912
913 for (Int_t modnum=0; modnum < 7; modnum++) {
b760c02e 914 symname = str;
915 symname += (modnum+1);
916 fgVolPath[kRICH-kFirstLayer][modnum] = symname.Data();
c8874495 917 }
918 }
274fcc1a 919
920 /********************* TRD layers 0-6 *******************/
921 {
de0b6220 922 TString strSM[18]={"ALIC_1/B077_1/BSEGMO0_1/BTRD0_1/UTR1_1/UTS1_1/UTI1_1/UT",
923 "ALIC_1/B077_1/BSEGMO1_1/BTRD1_1/UTR1_1/UTS1_1/UTI1_1/UT",
924 "ALIC_1/B077_1/BSEGMO2_1/BTRD2_1/UTR1_1/UTS1_1/UTI1_1/UT",
925 "ALIC_1/B077_1/BSEGMO3_1/BTRD3_1/UTR1_1/UTS1_1/UTI1_1/UT",
926 "ALIC_1/B077_1/BSEGMO4_1/BTRD4_1/UTR1_1/UTS1_1/UTI1_1/UT",
927 "ALIC_1/B077_1/BSEGMO5_1/BTRD5_1/UTR1_1/UTS1_1/UTI1_1/UT",
9ce7d00f 928 "ALIC_1/B077_1/BSEGMO6_1/BTRD6_1/UTR1_1/UTS1_1/UTI1_1/UT",
929 "ALIC_1/B077_1/BSEGMO7_1/BTRD7_1/UTR1_1/UTS1_1/UTI1_1/UT",
930 "ALIC_1/B077_1/BSEGMO8_1/BTRD8_1/UTR1_1/UTS1_1/UTI1_1/UT",
931 "ALIC_1/B077_1/BSEGMO9_1/BTRD9_1/UTR1_1/UTS1_1/UTI1_1/UT",
932 "ALIC_1/B077_1/BSEGMO10_1/BTRD10_1/UTR1_1/UTS1_1/UTI1_1/UT",
933 "ALIC_1/B077_1/BSEGMO11_1/BTRD11_1/UTR1_1/UTS1_1/UTI1_1/UT",
934 "ALIC_1/B077_1/BSEGMO12_1/BTRD12_1/UTR1_1/UTS1_1/UTI1_1/UT",
935 "ALIC_1/B077_1/BSEGMO13_1/BTRD13_1/UTR1_1/UTS1_1/UTI1_1/UT",
936 "ALIC_1/B077_1/BSEGMO14_1/BTRD14_1/UTR1_1/UTS1_1/UTI1_1/UT",
937 "ALIC_1/B077_1/BSEGMO15_1/BTRD15_1/UTR1_1/UTS1_1/UTI1_1/UT",
938 "ALIC_1/B077_1/BSEGMO16_1/BTRD16_1/UTR1_1/UTS1_1/UTI1_1/UT",
de0b6220 939 "ALIC_1/B077_1/BSEGMO17_1/BTRD17_1/UTR1_1/UTS1_1/UTI1_1/UT"};
274fcc1a 940 TString strPost = "_1";
a1a23a88 941 TString zeroStr = "0";
b760c02e 942 TString symname;
a1a23a88 943
e1e6896f 944 Int_t arTRDlayId[6] = {kTRD1, kTRD2, kTRD3, kTRD4, kTRD5, kTRD6};
274fcc1a 945
a1a23a88 946 for(Int_t layer=0; layer<6; layer++){
947 Int_t modnum=0;
948 for(Int_t sm = 0; sm < 18; sm++){
949 for(Int_t stacknum = 0; stacknum < 5; stacknum++){
950 Int_t chnum = layer + stacknum*6;
b760c02e 951 symname = strSM[sm];
952 if(chnum<10) symname += zeroStr;
953 symname += chnum;
954 symname += strPost;
955 fgVolPath[arTRDlayId[layer]-kFirstLayer][modnum] = symname.Data();
274fcc1a 956 modnum++;
957 }
958 }
959 }
960 }
961
03b18860 962}