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