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