]> git.uio.no Git - u/mrichter/AliRoot.git/blame - STEER/AliAlignObj.cxx
Do not hide variables from the outer scope (Solaris x86)
[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
090026bf 16/* $Id$ */
17
c18195b9 18//-----------------------------------------------------------------
7e154d52 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.
c18195b9 23//-----------------------------------------------------------------
995ad051 24#include <TGeoManager.h>
25#include <TGeoPhysicalNode.h>
090026bf 26#include <TMath.h>
276cb1b1 27#include "TObjString.h"
995ad051 28
c18195b9 29#include "AliAlignObj.h"
03b18860 30#include "AliTrackPointArray.h"
31#include "AliLog.h"
c5304981 32#include "AliAlignObjAngles.h"
98937d93 33
c18195b9 34ClassImp(AliAlignObj)
35
98937d93 36Int_t AliAlignObj::fgLayerSize[kLastLayer - kFirstLayer] = {
b760c02e 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
da027ef2 42 1638, // TOF
98937d93 43 1, 1, // PHOS ??
f4b3bbb7 44 7, // HMPID ??
98937d93 45 1 // MUON ??
46};
47
48const 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",
55 "TOF layer",
56 "?","?",
f4b3bbb7 57 "HMPID layer",
98937d93 58 "?"
59};
60
7604a026 61TString* AliAlignObj::fgVolPath[kLastLayer - kFirstLayer] = {
03b18860 62 0x0,0x0,
63 0x0,0x0,
64 0x0,0x0,
65 0x0,0x0,
66 0x0,0x0,0x0,
67 0x0,0x0,0x0,
68 0x0,
69 0x0,0x0,
70 0x0,
71 0x0
72};
73
c5304981 74AliAlignObj** AliAlignObj::fgAlignObjs[kLastLayer - kFirstLayer] = {
75 0x0,0x0,
76 0x0,0x0,
77 0x0,0x0,
78 0x0,0x0,
79 0x0,0x0,0x0,
80 0x0,0x0,0x0,
81 0x0,
82 0x0,0x0,
83 0x0,
84 0x0
85};
86
c18195b9 87//_____________________________________________________________________________
88AliAlignObj::AliAlignObj():
fe12e09c 89 fVolPath(),
c18195b9 90 fVolUID(0)
91{
03b18860 92 // default constructor
b760c02e 93 InitSymNames();
c18195b9 94}
95
96//_____________________________________________________________________________
b760c02e 97AliAlignObj::AliAlignObj(const char* symname, UShort_t voluid) :
fe12e09c 98 TObject(),
b760c02e 99 fVolPath(symname),
fe12e09c 100 fVolUID(voluid)
d9cc42ed 101{
102 // standard constructor
103 //
d9cc42ed 104}
105
d9cc42ed 106//_____________________________________________________________________________
c18195b9 107AliAlignObj::AliAlignObj(const AliAlignObj& theAlignObj) :
fe12e09c 108 TObject(theAlignObj),
b760c02e 109 fVolPath(theAlignObj.GetSymName()),
fe12e09c 110 fVolUID(theAlignObj.GetVolUID())
c18195b9 111{
112 //copy constructor
c18195b9 113}
114
115//_____________________________________________________________________________
116AliAlignObj &AliAlignObj::operator =(const AliAlignObj& theAlignObj)
117{
118 // assignment operator
119 if(this==&theAlignObj) return *this;
b760c02e 120 fVolPath = theAlignObj.GetSymName();
c18195b9 121 fVolUID = theAlignObj.GetVolUID();
122 return *this;
123}
124
38b3a170 125//_____________________________________________________________________________
126AliAlignObj &AliAlignObj::operator*=(const AliAlignObj& theAlignObj)
127{
128 // multiplication operator
129 // The operator can be used to 'combine'
130 // two alignment objects
131 TGeoHMatrix m1;
132 GetMatrix(m1);
133 TGeoHMatrix m2;
134 theAlignObj.GetMatrix(m2);
135 m1.MultiplyLeft(&m2);
136 SetMatrix(m1);
137 return *this;
138}
139
c18195b9 140//_____________________________________________________________________________
141AliAlignObj::~AliAlignObj()
142{
143 // dummy destructor
144}
145
befe2c08 146//_____________________________________________________________________________
147void AliAlignObj::SetVolUID(ELayerID detId, Int_t modId)
148{
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).
153 //
154 fVolUID = LayerToVolUID(detId,modId);
155}
156
157//_____________________________________________________________________________
158void AliAlignObj::GetVolUID(ELayerID &layerId, Int_t &modId) const
159{
7e154d52 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.
befe2c08 166 //
167 layerId = VolUIDToLayer(fVolUID,modId);
168}
169
b760c02e 170//_____________________________________________________________________________
171Bool_t AliAlignObj::GetPars(Double_t tr[], Double_t angles[]) const
172{
173 GetTranslation(tr);
174 return GetAngles(angles);
175}
176
4b94e753 177//_____________________________________________________________________________
178Int_t AliAlignObj::GetLevel() const
179{
85fbf070 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
183 //
184 if(!gGeoManager){
185 AliWarning("gGeoManager doesn't exist or it is still opened: unable to return meaningful level value.");
186 return (-1);
187 }
188 const char* symname = GetSymName();
189 const char* path;
190 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
191 if(pne){
192 path = pne->GetTitle();
193 }else{
194 path = symname;
195 }
196
197 TString path_str = path;
198 if(path_str[0]!='/') path_str.Prepend('/');
199 return path_str.CountChar('/');
4b94e753 200}
201
202//_____________________________________________________________________________
203Int_t AliAlignObj::Compare(const TObject *obj) const
204{
205 // Compare the levels of two
206 // alignment objects
207 // Used in the sorting during
208 // the application of alignment
209 // objects to the geometry
7e154d52 210 //
4b94e753 211 Int_t level = GetLevel();
212 Int_t level2 = ((AliAlignObj *)obj)->GetLevel();
213 if (level == level2)
214 return 0;
215 else
216 return ((level > level2) ? 1 : -1);
217}
218
c18195b9 219//_____________________________________________________________________________
220void AliAlignObj::AnglesToMatrix(const Double_t *angles, Double_t *rot) const
221{
fdf65bb5 222 // Calculates the rotation matrix using the
223 // Euler angles in "x y z" notation
7e154d52 224 //
c18195b9 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]);
232
233 rot[0] = costhe*cosphi;
234 rot[1] = -costhe*sinphi;
235 rot[2] = sinthe;
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;
242}
243
244//_____________________________________________________________________________
245Bool_t AliAlignObj::MatrixToAngles(const Double_t *rot, Double_t *angles) const
246{
fdf65bb5 247 // Calculates the Euler angles in "x y z" notation
248 // using the rotation matrix
b760c02e 249 // Returns false in case the rotation angles can not be
250 // extracted from the matrix
7e154d52 251 //
b760c02e 252 if(TMath::Abs(rot[0])<1e-7 || TMath::Abs(rot[8])<1e-7) {
253 AliError("Failed to extract roll-pitch-yall angles!");
254 return kFALSE;
255 }
c18195b9 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]);
260 return kTRUE;
261}
262
03b18860 263//______________________________________________________________________________
264void AliAlignObj::Transform(AliTrackPoint &p) const
265{
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
7e154d52 270 //
03b18860 271 if (fVolUID != p.GetVolumeID())
272 AliWarning(Form("Alignment object ID is not equal to the space-point ID (%d != %d)",fVolUID,p.GetVolumeID()));
273
274 TGeoHMatrix m;
275 GetMatrix(m);
276 Double_t *rot = m.GetRotationMatrix();
277 Double_t *tr = m.GetTranslation();
278
279 Float_t xyzin[3],xyzout[3];
280 p.GetXYZ(xyzin);
281 for (Int_t i = 0; i < 3; i++)
282 xyzout[i] = tr[i]+
283 xyzin[0]*rot[3*i]+
284 xyzin[1]*rot[3*i+1]+
285 xyzin[2]*rot[3*i+2];
286 p.SetXYZ(xyzout);
287
288}
289
79e21da6 290//_____________________________________________________________________________
03b18860 291void AliAlignObj::Transform(AliTrackPointArray &array) const
292{
e1e6896f 293 // This method is used to transform all the track points
294 // from the input AliTrackPointArray
7e154d52 295 //
03b18860 296 AliTrackPoint p;
297 for (Int_t i = 0; i < array.GetNPoints(); i++) {
298 array.GetPoint(p,i);
299 Transform(p);
300 array.AddPoint(i,&p);
301 }
302}
303
c18195b9 304//_____________________________________________________________________________
305void AliAlignObj::Print(Option_t *) const
306{
307 // Print the contents of the
308 // alignment object in angles and
309 // matrix representations
7e154d52 310 //
c18195b9 311 Double_t tr[3];
312 GetTranslation(tr);
313 Double_t angles[3];
314 GetAngles(angles);
315 TGeoHMatrix m;
316 GetMatrix(m);
317 const Double_t *rot = m.GetRotationMatrix();
c18195b9 318
b760c02e 319 printf("Volume=%s\n",GetSymName());
c041444f 320 if (GetVolUID() != 0) {
321 ELayerID layerId;
322 Int_t modId;
323 GetVolUID(layerId,modId);
324 printf("VolumeID=%d LayerID=%d ( %s ) ModuleID=%d\n", GetVolUID(),layerId,LayerName(layerId),modId);
325 }
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]);
329
330}
331
332//_____________________________________________________________________________
333Int_t AliAlignObj::LayerSize(Int_t layerId)
334{
7e154d52 335 // Get the layer size for layer corresponding to layerId.
f4b3bbb7 336 // Implemented only for ITS,TPC,TRD,TOF and HMPID
7e154d52 337 //
c041444f 338 if (layerId < kFirstLayer || layerId >= kLastLayer) {
339 AliErrorClass(Form("Invalid layer index %d ! Layer range is (%d -> %d) !",layerId,kFirstLayer,kLastLayer));
340 return 0;
341 }
342 else {
343 return fgLayerSize[layerId - kFirstLayer];
344 }
345}
346
347//_____________________________________________________________________________
348const char* AliAlignObj::LayerName(Int_t layerId)
349{
7e154d52 350 // Get the layer name corresponding to layerId.
f4b3bbb7 351 // Implemented only for ITS,TPC,TRD,TOF and HMPID
7e154d52 352 //
c041444f 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!";
356 }
357 else {
358 return fgLayerName[layerId - kFirstLayer];
359 }
c18195b9 360}
361
c18195b9 362//_____________________________________________________________________________
befe2c08 363UShort_t AliAlignObj::LayerToVolUID(ELayerID layerId, Int_t modId)
c18195b9 364{
7e154d52 365 // From detector (layer) name and module number (according to detector
366 // internal numbering) build the unique numerical identity of that volume
367 // inside ALICE
befe2c08 368 // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
369 // remaining 11 for module ID inside det (2048 possible values).
c18195b9 370 //
befe2c08 371 return ((UShort_t(layerId) << 11) | UShort_t(modId));
c18195b9 372}
373
46ae650f 374//_____________________________________________________________________________
375UShort_t AliAlignObj::LayerToVolUID(Int_t layerId, Int_t modId)
376{
7e154d52 377 // From detector (layer) name and module number (according to detector
378 // internal numbering) build the unique numerical identity of that volume
379 // inside ALICE
46ae650f 380 // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
381 // remaining 11 for module ID inside det (2048 possible values).
382 //
383 return ((UShort_t(layerId) << 11) | UShort_t(modId));
384}
385
c18195b9 386//_____________________________________________________________________________
befe2c08 387AliAlignObj::ELayerID AliAlignObj::VolUIDToLayer(UShort_t voluid, Int_t &modId)
c18195b9 388{
7e154d52 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.
befe2c08 394 //
395 modId = voluid & 0x7ff;
c18195b9 396
befe2c08 397 return VolUIDToLayer(voluid);
c18195b9 398}
399
400//_____________________________________________________________________________
befe2c08 401AliAlignObj::ELayerID AliAlignObj::VolUIDToLayer(UShort_t voluid)
c18195b9 402{
7e154d52 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
befe2c08 407 //
408 return ELayerID((voluid >> 11) & 0x1f);
c18195b9 409}
03b18860 410
b760c02e 411//_____________________________________________________________________________
412void AliAlignObj::SetPars(Double_t x, Double_t y, Double_t z,
413 Double_t psi, Double_t theta, Double_t phi)
414{
32898fe7 415 // Set the global delta transformation by passing 3 angles (expressed in
416 // degrees) and 3 shifts (in centimeters)
7e154d52 417 //
b760c02e 418 SetTranslation(x,y,z);
419 SetRotation(psi,theta,phi);
420}
421
1bfe7ffc 422//_____________________________________________________________________________
423Bool_t AliAlignObj::SetLocalPars(Double_t x, Double_t y, Double_t z,
424 Double_t psi, Double_t theta, Double_t phi)
425{
32898fe7 426 // Set the global delta transformation by passing the parameters
427 // for the local delta transformation (3 shifts and 3 angles).
7e154d52 428 // In case that the TGeo was not initialized or not closed,
429 // returns false and the object parameters are not set.
430 //
b760c02e 431 TGeoHMatrix m;
432 Double_t tr[3] = {x, y, z};
433 m.SetTranslation(tr);
434 Double_t angles[3] = {psi, theta, phi};
435 Double_t rot[9];
436 AnglesToMatrix(angles,rot);
437 m.SetRotation(rot);
438
439 return SetLocalMatrix(m);
440
441}
442
32898fe7 443//_____________________________________________________________________________
444Bool_t AliAlignObj::SetLocalTranslation(Double_t x, Double_t y, Double_t z)
445{
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.
451 //
452 TGeoHMatrix m;
453 Double_t tr[3] = {x, y, z};
454 m.SetTranslation(tr);
455
456 return SetLocalMatrix(m);
457
458}
459
460//_____________________________________________________________________________
461Bool_t AliAlignObj::SetLocalTranslation(const TGeoMatrix& m)
462{
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.
467 //
468 const Double_t* tr = m.GetTranslation();
469 TGeoHMatrix mtr;
470 mtr.SetTranslation(tr);
471
472 return SetLocalMatrix(mtr);
473
474}
475
476//_____________________________________________________________________________
477Bool_t AliAlignObj::SetLocalRotation(Double_t psi, Double_t theta, Double_t phi)
478{
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.
484 //
485 TGeoHMatrix m;
486 Double_t angles[3] = {psi, theta, phi};
487 Double_t rot[9];
488 AnglesToMatrix(angles,rot);
489 m.SetRotation(rot);
490
491 return SetLocalMatrix(m);
492
493}
494
495//_____________________________________________________________________________
496Bool_t AliAlignObj::SetLocalRotation(const TGeoMatrix& m)
497{
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.
502 //
503 TGeoHMatrix rotm;
504 const Double_t* rot = m.GetRotationMatrix();
505 rotm.SetRotation(rot);
506
507 return SetLocalMatrix(rotm);
508
509}
510
b760c02e 511//_____________________________________________________________________________
512Bool_t AliAlignObj::SetLocalMatrix(const TGeoMatrix& m)
513{
32898fe7 514 // Set the global delta transformation by passing the TGeo matrix
515 // for the local delta transformation.
7e154d52 516 // In case that the TGeo was not initialized or not closed,
517 // returns false and the object parameters are not set.
518 //
1bfe7ffc 519 if (!gGeoManager || !gGeoManager->IsClosed()) {
520 AliError("Can't set the alignment object parameters! gGeoManager doesn't exist or it is still opened!");
521 return kFALSE;
522 }
523
b760c02e 524 const char* symname = GetSymName();
525 TGeoPhysicalNode* node;
526 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
527 if(pne){
528 node = gGeoManager->MakeAlignablePN(pne);
529 }else{
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);
532 }
533
1bfe7ffc 534 if (!node) {
b760c02e 535 AliError(Form("Volume name or path %s not valid!",symname));
1bfe7ffc 536 return kFALSE;
537 }
538 if (node->IsAligned())
b760c02e 539 AliWarning(Form("Volume %s has been already misaligned!",symname));
1bfe7ffc 540
b760c02e 541 TGeoHMatrix m1;
542 const Double_t *tr = m.GetTranslation();
543 m1.SetTranslation(tr);
544 const Double_t* rot = m.GetRotationMatrix();
545 m1.SetRotation(rot);
1bfe7ffc 546
547 TGeoHMatrix align,gprime,gprimeinv;
548 gprime = *node->GetMatrix();
549 gprimeinv = gprime.Inverse();
b760c02e 550 m1.Multiply(&gprimeinv);
551 m1.MultiplyLeft(&gprime);
1bfe7ffc 552
b760c02e 553 return SetMatrix(m1);
554}
1bfe7ffc 555
b760c02e 556//_____________________________________________________________________________
557Bool_t AliAlignObj::SetMatrix(const TGeoMatrix& m)
558{
32898fe7 559 // Set the global delta transformation by passing the TGeoMatrix
560 // for it
7e154d52 561 //
b760c02e 562 SetTranslation(m);
563 return SetRotation(m);
1bfe7ffc 564}
565
32898fe7 566//_____________________________________________________________________________
567Bool_t AliAlignObj::GetLocalPars(Double_t transl[], Double_t angles[]) const
568{
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.
573 //
574 if(!GetLocalTranslation(transl)) return kFALSE;
575 return GetLocalAngles(angles);
576}
577
578//_____________________________________________________________________________
579Bool_t AliAlignObj::GetLocalTranslation(Double_t* tr) const
580{
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.
585 //
586 TGeoHMatrix ml;
587 if(!GetLocalMatrix(ml)) return kFALSE;
588 const Double_t* transl;
589 transl = ml.GetTranslation();
590 tr[0]=transl[0];
591 tr[1]=transl[1];
592 tr[2]=transl[2];
593 return kTRUE;
594}
595
596//_____________________________________________________________________________
597Bool_t AliAlignObj::GetLocalAngles(Double_t* angles) const
598{
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.
603 //
604 TGeoHMatrix ml;
605 if(!GetLocalMatrix(ml)) return kFALSE;
606 const Double_t *rot = ml.GetRotationMatrix();
607 return MatrixToAngles(rot,angles);
608}
609
610//_____________________________________________________________________________
611Bool_t AliAlignObj::GetLocalMatrix(TGeoHMatrix& m) const
612{
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.
616 //
617 if (!gGeoManager || !gGeoManager->IsClosed()) {
618 AliError("Can't set the alignment object parameters! gGeoManager doesn't exist or it is still opened!");
619 return kFALSE;
620 }
621
622 const char* symname = GetSymName();
623 TGeoPhysicalNode* node;
624 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
625 if(pne){
626 node = gGeoManager->MakeAlignablePN(pne);
627 }else{
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);
630 }
631
632 if (!node) {
633 AliError(Form("Volume name or path %s not valid!",symname));
634 return kFALSE;
635 }
636 if (node->IsAligned())
637 AliWarning(Form("Volume %s has been already misaligned!",symname));
638
639 GetMatrix(m);
640 TGeoHMatrix gprime,gprimeinv;
641 gprime = *node->GetMatrix();
642 gprimeinv = gprime.Inverse();
643 m.Multiply(&gprime);
644 m.MultiplyLeft(&gprimeinv);
645
646 return kTRUE;
647}
648
995ad051 649//_____________________________________________________________________________
650Bool_t AliAlignObj::ApplyToGeometry()
651{
7e154d52 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
655 //
995ad051 656 if (!gGeoManager || !gGeoManager->IsClosed()) {
657 AliError("Can't apply the alignment object! gGeoManager doesn't exist or it is still opened!");
658 return kFALSE;
659 }
660
b760c02e 661 const char* symname = GetSymName();
662 const char* path;
663 TGeoPhysicalNode* node;
664 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
665 if(pne){
b760c02e 666 path = pne->GetTitle();
7e154d52 667 node = gGeoManager->MakeAlignablePN(pne);
b760c02e 668 }else{
669 AliWarning(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
670 path=symname;
7e154d52 671 if (!gGeoManager->CheckPath(path)) {
672 AliError(Form("Volume path %s not valid!",path));
b760c02e 673 return kFALSE;
674 }
7e154d52 675 if (gGeoManager->GetListOfPhysicalNodes()->FindObject(path)) {
676 AliError(Form("Volume %s has already been misaligned!",path));
b760c02e 677 return kFALSE;
678 }
679 node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(path);
995ad051 680 }
48cac49d 681
48cac49d 682 if (!node) {
b760c02e 683 AliError(Form("Volume path %s not valid!",path));
995ad051 684 return kFALSE;
685 }
686
687 TGeoHMatrix align,gprime;
688 gprime = *node->GetMatrix();
689 GetMatrix(align);
690 gprime.MultiplyLeft(&align);
691 TGeoHMatrix *ginv = new TGeoHMatrix;
692 TGeoHMatrix *g = node->GetMatrix(node->GetLevel()-1);
693 *ginv = g->Inverse();
694 *ginv *= gprime;
b760c02e 695 AliAlignObj::ELayerID layerId; // unique identity for layer in the alobj
696 Int_t modId; // unique identity for volume inside layer in the alobj
995ad051 697 GetVolUID(layerId, modId);
b760c02e 698 AliDebug(2,Form("Aligning volume %s of detector layer %d with local ID %d",symname,layerId,modId));
995ad051 699 node->Align(ginv);
700
701 return kTRUE;
702}
703
704//_____________________________________________________________________________
b760c02e 705Bool_t AliAlignObj::GetFromGeometry(const char *symname, AliAlignObj &alobj)
995ad051 706{
b760c02e 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!!
7e154d52 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.
b760c02e 714 //
995ad051 715
716 // Reset the alignment object
717 alobj.SetPars(0,0,0,0,0,0);
b760c02e 718 alobj.SetSymName(symname);
995ad051 719
720 if (!gGeoManager || !gGeoManager->IsClosed()) {
721 AliErrorClass("Can't get the alignment object! gGeoManager doesn't exist or it is still opened!");
722 return kFALSE;
723 }
724
725 if (!gGeoManager->GetListOfPhysicalNodes()) {
726 AliErrorClass("Can't get the alignment object! gGeoManager doesn't contain any aligned nodes!");
727 return kFALSE;
728 }
729
b760c02e 730 const char *path;
731 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
732 if(pne){
733 path = pne->GetTitle();
734 }else{
735 AliWarningClass(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
736 path = symname;
737 }
995ad051 738 TObjArray* nodesArr = gGeoManager->GetListOfPhysicalNodes();
739 TGeoPhysicalNode* node = NULL;
740 for (Int_t iNode = 0; iNode < nodesArr->GetEntriesFast(); iNode++) {
b760c02e 741 TGeoPhysicalNode* tempNode = (TGeoPhysicalNode*) nodesArr->UncheckedAt(iNode);
742 const char *nodePath = tempNode->GetName();
1fbe4bbd 743 if (strcmp(path,nodePath) == 0) {
b760c02e 744 node = tempNode;
745 break;
746 }
995ad051 747 }
b760c02e 748
995ad051 749 if (!node) {
1fbe4bbd 750 if (!gGeoManager->cd(path)) {
751 AliErrorClass(Form("%s not valid neither as symbolic volume name nor as volume path!",path));
e1c4b551 752 return kFALSE;
753 }
754 else {
1fbe4bbd 755 AliWarningClass(Form("Volume (%s) has not been misaligned!",path));
e1c4b551 756 return kTRUE;
757 }
995ad051 758 }
759
760 TGeoHMatrix align,gprime,g,ginv,l;
761 gprime = *node->GetMatrix();
762 l = *node->GetOriginalMatrix();
763 g = *node->GetMatrix(node->GetLevel()-1);
764 g *= l;
765 ginv = g.Inverse();
766 align = gprime * ginv;
995ad051 767
b760c02e 768 return alobj.SetMatrix(align);
995ad051 769}
770
79e21da6 771//_____________________________________________________________________________
276cb1b1 772Bool_t AliAlignObj::GetOrigGlobalMatrix(const char *symname, TGeoHMatrix &m)
773{
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
778 // is invalid.
779 //
780
781 if (!gGeoManager || !gGeoManager->IsClosed()) {
782 AliErrorClass("Can't get the original global matrix! gGeoManager doesn't exist or it is still opened!");
783 return kFALSE;
784 }
785
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));
790 return kFALSE;
791 }
792 else {
793 m = *gGeoManager->GetCurrentMatrix();
794 return kTRUE;
795 }
796 }
797
798 const char* path = NULL;
799 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
800 if(pne){
801 path = pne->GetTitle();
802 }else{
803 AliWarningClass(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
804 path=symname;
805 }
806
807 if (!gGeoManager->CheckPath(path)) {
808 AliErrorClass(Form("Volume path %s not valid!",path));
809 return kFALSE;
810 }
811
812 TString pathStr = path;
813 TObjArray *pathArr = pathStr.Tokenize('/');
814 TIter iter(pathArr);
815 TString nodeStr = "";
816 m.Clear();
817
818 TObjString *str = NULL;
819 while((str = (TObjString*) iter.Next())){
820 nodeStr.Append("/");
821 nodeStr.Append(str->String());
822
823 TGeoMatrix *lm = NULL;
f9ce5d7f 824 TGeoPhysicalNode *physNode = NULL;
825 if ((physNode = (TGeoPhysicalNode *)gGeoManager->GetListOfPhysicalNodes()->FindObject(nodeStr.Data()))) {
276cb1b1 826 lm = physNode->GetOriginalMatrix();
827 if (!lm) lm = physNode->GetNode()->GetMatrix();
f9ce5d7f 828 } else {
276cb1b1 829 gGeoManager->cd(nodeStr.Data());
830 TGeoNode *node = gGeoManager->GetCurrentNode();
831 lm = node->GetMatrix();
832 }
833 m.Multiply(lm);
834 }
835
f9ce5d7f 836 pathArr->Delete();
276cb1b1 837 delete pathArr;
838
839 return kTRUE;
840}
841
842//_____________________________________________________________________________
c5304981 843void AliAlignObj::InitAlignObjFromGeometry()
844{
845 // Loop over all alignable volumes and extract
846 // the corresponding alignment objects from
847 // the TGeo geometry
25b4e81e 848
849 if(fgAlignObjs[0]) return;
c5304981 850
b760c02e 851 InitSymNames();
c5304981 852
c041444f 853 for (Int_t iLayer = kFirstLayer; iLayer < AliAlignObj::kLastLayer; iLayer++) {
854 fgAlignObjs[iLayer-kFirstLayer] = new AliAlignObj*[AliAlignObj::LayerSize(iLayer)];
c5304981 855 for (Int_t iModule = 0; iModule < AliAlignObj::LayerSize(iLayer); iModule++) {
c041444f 856 UShort_t volid = AliAlignObj::LayerToVolUID(iLayer,iModule);
b760c02e 857 fgAlignObjs[iLayer-kFirstLayer][iModule] = new AliAlignObjAngles("",volid,0,0,0,0,0,0,kTRUE);
858 const char *symname = SymName(volid);
859 if (!GetFromGeometry(symname, *fgAlignObjs[iLayer-kFirstLayer][iModule]))
860 AliErrorClass(Form("Failed to extract the alignment object for the volume (ID=%d and path=%s) !",volid,symname));
c5304981 861 }
862 }
863
864}
865
e1e6896f 866//_____________________________________________________________________________
867AliAlignObj* AliAlignObj::GetAlignObj(UShort_t voluid) {
868 // Returns the alignment object for given volume ID
7e154d52 869 //
e1e6896f 870 Int_t modId;
871 ELayerID layerId = VolUIDToLayer(voluid,modId);
872 return GetAlignObj(layerId,modId);
873}
874
c5304981 875//_____________________________________________________________________________
876AliAlignObj* AliAlignObj::GetAlignObj(ELayerID layerId, Int_t modId)
877{
7e154d52 878 // Returns pointer to alignment object given its layer and module ID
879 //
c5304981 880 if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
881 AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
882 return NULL;
883 }
b760c02e 884 InitAlignObjFromGeometry();
885
c5304981 886 return fgAlignObjs[layerId-kFirstLayer][modId];
887}
888
e1e6896f 889//_____________________________________________________________________________
b760c02e 890const char* AliAlignObj::SymName(UShort_t voluid) {
7e154d52 891 // Returns the symbolic volume name for given volume ID
892 //
e1e6896f 893 Int_t modId;
894 ELayerID layerId = VolUIDToLayer(voluid,modId);
b760c02e 895 return SymName(layerId,modId);
e1e6896f 896}
897
e7570944 898//_____________________________________________________________________________
b760c02e 899const char* AliAlignObj::SymName(ELayerID layerId, Int_t modId)
e7570944 900{
7e154d52 901 // Returns the symbolic volume name given for a given layer
902 // and module ID
903 //
e7570944 904 if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
905 AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
906 return NULL;
907 }
b760c02e 908 InitSymNames();
909
e7570944 910 return fgVolPath[layerId-kFirstLayer][modId].Data();
911}
912
03b18860 913//_____________________________________________________________________________
b760c02e 914void AliAlignObj::InitSymNames()
03b18860 915{
7e154d52 916 // Initialize the LUTs which associate the symbolic volume names
917 // for each alignable volume with their unique numerical identity.
918 // The LUTs are static, so they are created during the instantiation
919 // of the first intance of AliAlignObj
920 //
03b18860 921 if (fgVolPath[0]) return;
922
923 for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++)
7604a026 924 fgVolPath[iLayer] = new TString[fgLayerSize[iLayer]];
03b18860 925
7e154d52 926 TString symname;
927 Int_t modnum; // in the following, set it to 0 at the start of each layer
928
929 /********************* ITS layers ***********************/
930 TString strSPD = "ITS/SPD";
931 TString strSDD = "ITS/SDD";
932 TString strSSD = "ITS/SSD";
933 TString strStave = "/Stave";
934 TString strLadder = "/Ladder";
935 TString strSector = "/Sector";
936 TString strSensor = "/Sensor";
937 TString strEntryName1;
938 TString strEntryName2;
939
03b18860 940 /********************* SPD layer1 ***********************/
941 {
7e154d52 942 modnum = 0;
03b18860 943
944 for(Int_t c1 = 1; c1<=10; c1++){
7e154d52 945 strEntryName1 = strSPD;
946 strEntryName1 += 0;
947 strEntryName1 += strSector;
948 strEntryName1 += (c1-1);
03b18860 949 for(Int_t c2 =1; c2<=2; c2++){
7e154d52 950 strEntryName2 = strEntryName1;
951 strEntryName2 += strStave;
952 strEntryName2 += (c2-1);
03b18860 953 for(Int_t c3 =1; c3<=4; c3++){
7e154d52 954 symname = strEntryName2;
955 symname += strLadder;
956 symname += (c3-1);
957 fgVolPath[kSPD1-kFirstLayer][modnum] = symname.Data();
03b18860 958 modnum++;
959 }
960 }
961 }
962 }
963
964 /********************* SPD layer2 ***********************/
965 {
7e154d52 966 modnum = 0;
03b18860 967
968 for(Int_t c1 = 1; c1<=10; c1++){
7e154d52 969 strEntryName1 = strSPD;
970 strEntryName1 += 1;
971 strEntryName1 += strSector;
972 strEntryName1 += (c1-1);
03b18860 973 for(Int_t c2 =1; c2<=4; c2++){
7e154d52 974 strEntryName2 = strEntryName1;
975 strEntryName2 += strStave;
976 strEntryName2 += (c2-1);
03b18860 977 for(Int_t c3 =1; c3<=4; c3++){
7e154d52 978 symname = strEntryName2;
979 symname += strLadder;
980 symname += (c3-1);
981 fgVolPath[kSPD2-kFirstLayer][modnum] = symname.Data();
03b18860 982 modnum++;
983 }
984 }
985 }
986 }
987
988 /********************* SDD layer1 ***********************/
989 {
7e154d52 990 modnum=0;
03b18860 991
992 for(Int_t c1 = 1; c1<=14; c1++){
7e154d52 993 strEntryName1 = strSDD;
994 strEntryName1 += 2;
995 strEntryName1 +=strLadder;
996 strEntryName1 += (c1-1);
03b18860 997 for(Int_t c2 =1; c2<=6; c2++){
7e154d52 998 symname = strEntryName1;
999 symname += strSensor;
1000 symname += (c2-1);
1001 fgVolPath[kSDD1-kFirstLayer][modnum] = symname.Data();
03b18860 1002 modnum++;
1003 }
1004 }
1005 }
1006
1007 /********************* SDD layer2 ***********************/
1008 {
7e154d52 1009 modnum=0;
03b18860 1010
1011 for(Int_t c1 = 1; c1<=22; c1++){
7e154d52 1012 strEntryName1 = strSDD;
1013 strEntryName1 += 3;
1014 strEntryName1 +=strLadder;
1015 strEntryName1 += (c1-1);
03b18860 1016 for(Int_t c2 = 1; c2<=8; c2++){
7e154d52 1017 symname = strEntryName1;
1018 symname += strSensor;
1019 symname += (c2-1);
1020 fgVolPath[kSDD2-kFirstLayer][modnum] = symname.Data();
03b18860 1021 modnum++;
1022 }
1023 }
1024 }
1025
1026 /********************* SSD layer1 ***********************/
1027 {
7e154d52 1028 modnum=0;
03b18860 1029
1030 for(Int_t c1 = 1; c1<=34; c1++){
7e154d52 1031 strEntryName1 = strSSD;
1032 strEntryName1 += 4;
1033 strEntryName1 +=strLadder;
1034 strEntryName1 += (c1-1);
03b18860 1035 for(Int_t c2 = 1; c2<=22; c2++){
7e154d52 1036 symname = strEntryName1;
1037 symname += strSensor;
1038 symname += (c2-1);
1039 fgVolPath[kSSD1-kFirstLayer][modnum] = symname.Data();
03b18860 1040 modnum++;
1041 }
1042 }
1043 }
1044
7e154d52 1045 /********************* SSD layer2 ***********************/
03b18860 1046 {
7e154d52 1047 modnum=0;
03b18860 1048
1049 for(Int_t c1 = 1; c1<=38; c1++){
7e154d52 1050 strEntryName1 = strSSD;
1051 strEntryName1 += 5;
1052 strEntryName1 +=strLadder;
1053 strEntryName1 += (c1-1);
03b18860 1054 for(Int_t c2 = 1; c2<=25; c2++){
7e154d52 1055 symname = strEntryName1;
1056 symname += strSensor;
1057 symname += (c2-1);
1058 fgVolPath[kSSD2-kFirstLayer][modnum] = symname.Data();
03b18860 1059 modnum++;
1060 }
1061 }
1062 }
1063
7e154d52 1064
1065 /*************** TPC inner and outer layers ****************/
1066 TString sAsector="TPC/EndcapA/Sector";
1067 TString sCsector="TPC/EndcapC/Sector";
1068 TString sInner="/InnerChamber";
1069 TString sOuter="/OuterChamber";
1070
e7570944 1071 /*************** TPC inner chambers' layer ****************/
1072 {
7e154d52 1073 modnum = 0;
e7570944 1074
1075 for(Int_t cnt=1; cnt<=18; cnt++){
7e154d52 1076 symname = sAsector;
b760c02e 1077 symname += cnt;
7e154d52 1078 symname += sInner;
b760c02e 1079 fgVolPath[kTPC1-kFirstLayer][modnum] = symname.Data();
e7570944 1080 modnum++;
1081 }
1082 for(Int_t cnt=1; cnt<=18; cnt++){
7e154d52 1083 symname = sCsector;
b760c02e 1084 symname += cnt;
7e154d52 1085 symname += sInner;
b760c02e 1086 fgVolPath[kTPC1-kFirstLayer][modnum] = symname.Data();
e7570944 1087 modnum++;
1088 }
1089 }
1090
1091 /*************** TPC outer chambers' layer ****************/
1092 {
7e154d52 1093 modnum = 0;
e7570944 1094
1095 for(Int_t cnt=1; cnt<=18; cnt++){
7e154d52 1096 symname = sAsector;
b760c02e 1097 symname += cnt;
7e154d52 1098 symname += sOuter;
b760c02e 1099 fgVolPath[kTPC2-kFirstLayer][modnum] = symname.Data();
e7570944 1100 modnum++;
1101 }
1102 for(Int_t cnt=1; cnt<=18; cnt++){
7e154d52 1103 symname = sCsector;
b760c02e 1104 symname += cnt;
7e154d52 1105 symname += sOuter;
b760c02e 1106 fgVolPath[kTPC2-kFirstLayer][modnum] = symname.Data();
e7570944 1107 modnum++;
1108 }
1109 }
1110
9abb5d7b 1111 /********************* TOF layer ***********************/
1112 {
7e154d52 1113 modnum=0;
1114
9abb5d7b 1115 Int_t nstrA=15;
1116 Int_t nstrB=19;
da027ef2 1117 Int_t nstrC=19;
7e154d52 1118 Int_t nSectors=18;
1119 Int_t nStrips=nstrA+2*nstrB+2*nstrC;
1120
1121 TString snSM = "TOF/sm";
1122 TString snSTRIP = "/strip";
1123
1124 for (Int_t isect = 0; isect < nSectors; isect++) {
1125 for (Int_t istr = 1; istr <= nStrips; istr++) {
1126 symname = snSM;
1127 symname += Form("%02d",isect);
1128 symname += snSTRIP;
1129 symname += Form("%02d",istr);
1130 fgVolPath[kTOF-kFirstLayer][modnum] = symname.Data();
1131 modnum++;
1132 }
9abb5d7b 1133 }
1134 }
c8874495 1135
f4b3bbb7 1136 /********************* HMPID layer ***********************/
c8874495 1137 {
c1f4a635 1138 TString str = "/HMPID/Chamber";
c8874495 1139
7e154d52 1140 for (modnum=0; modnum < 7; modnum++) {
b760c02e 1141 symname = str;
c1f4a635 1142 symname += modnum;
f4b3bbb7 1143 fgVolPath[kHMPID-kFirstLayer][modnum] = symname.Data();
c8874495 1144 }
1145 }
274fcc1a 1146
7e154d52 1147 /********************* TRD layers 1-6 *******************/
1148 //!! 6 layers with index increasing in outwards direction
274fcc1a 1149 {
e1e6896f 1150 Int_t arTRDlayId[6] = {kTRD1, kTRD2, kTRD3, kTRD4, kTRD5, kTRD6};
274fcc1a 1151
7e154d52 1152 TString snStr = "TRD/sm";
1153 TString snApp1 = "/st";
1154 TString snApp2 = "/pl";
1155
a1a23a88 1156 for(Int_t layer=0; layer<6; layer++){
7e154d52 1157 modnum=0;
1158 for (Int_t isect = 0; isect < 18; isect++) {
1159 for (Int_t icham = 0; icham < 5; icham++) {
1160 symname = snStr;
1161 symname += Form("%02d",isect);
1162 symname += snApp1;
1163 symname += icham;
1164 symname += snApp2;
1165 symname += layer;
b760c02e 1166 fgVolPath[arTRDlayId[layer]-kFirstLayer][modnum] = symname.Data();
274fcc1a 1167 modnum++;
1168 }
1169 }
1170 }
1171 }
03b18860 1172}
7e154d52 1173