1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
16 //-----------------------------------------------------------------
17 // Implementation of the alignment object class through the abstract
18 // class AliAlignObj. From it two derived concrete representation of
19 // alignment object class (AliAlignObjAngles, AliAlignObjMatrix) are
20 // derived in separate files.
21 //-----------------------------------------------------------------
22 /*****************************************************************************
23 * AliAlignObjAngles: derived alignment class storing alignment information *
24 * for a single volume in form of three doubles for the translation *
25 * and three doubles for the rotation expressed with the euler angles *
26 * in the xyz-convention (http://mathworld.wolfram.com/EulerAngles.html), *
27 * also known as roll, pitch, yaw. PLEASE NOTE THE ANGLES SIGNS ARE *
28 * INVERSE WITH RESPECT TO THIS REFERENCE!!! In this way the representation*
29 * is fully consistent with the TGeo Rotation methods. *
30 *****************************************************************************/
32 #include <TGeoManager.h>
33 #include <TGeoPhysicalNode.h>
35 #include "AliAlignObj.h"
36 #include "AliTrackPointArray.h"
41 Int_t AliAlignObj::fgLayerSize[kLastLayer - kFirstLayer] = {
46 90, 90, 90, 90, 90, 90, // TRD
53 const char* AliAlignObj::fgLayerName[kLastLayer - kFirstLayer] = {
54 "ITS inner pixels layer", "ITS outer pixels layer",
55 "ITS inner drifts layer", "ITS outer drifts layer",
56 "ITS inner strips layer", "ITS outer strips layer",
57 "TPC inner chambers layer", "TPC outer chambers layer",
58 "TRD chambers layer 1", "TRD chambers layer 2", "TRD chambers layer 3",
59 "TRD chambers layer 4", "TRD chambers layer 5", "TRD chambers layer 6",
66 TString* AliAlignObj::fgVolPath[kLastLayer - kFirstLayer] = {
79 //_____________________________________________________________________________
80 AliAlignObj::AliAlignObj():
83 // default constructor
87 //_____________________________________________________________________________
88 AliAlignObj::AliAlignObj(const AliAlignObj& theAlignObj) :
92 fVolPath = theAlignObj.GetVolPath();
93 fVolUID = theAlignObj.GetVolUID();
96 //_____________________________________________________________________________
97 AliAlignObj &AliAlignObj::operator =(const AliAlignObj& theAlignObj)
99 // assignment operator
100 if(this==&theAlignObj) return *this;
101 fVolPath = theAlignObj.GetVolPath();
102 fVolUID = theAlignObj.GetVolUID();
106 //_____________________________________________________________________________
107 AliAlignObj &AliAlignObj::operator*=(const AliAlignObj& theAlignObj)
109 // multiplication operator
110 // The operator can be used to 'combine'
111 // two alignment objects
115 theAlignObj.GetMatrix(m2);
116 m1.MultiplyLeft(&m2);
121 //_____________________________________________________________________________
122 AliAlignObj::~AliAlignObj()
127 //_____________________________________________________________________________
128 void AliAlignObj::SetVolUID(ELayerID detId, Int_t modId)
130 // From detector name and module number (according to detector numbering)
131 // build fVolUID, unique numerical identity of that volume inside ALICE
132 // fVolUID is 16 bits, first 5 reserved for detID (32 possible values),
133 // remaining 11 for module ID inside det (2048 possible values).
135 fVolUID = LayerToVolUID(detId,modId);
138 //_____________________________________________________________________________
139 void AliAlignObj::GetVolUID(ELayerID &layerId, Int_t &modId) const
141 // From detector name and module number (according to detector numbering)
142 // build fVolUID, unique numerical identity of that volume inside ALICE
143 // fVolUID is 16 bits, first 5 reserved for detID (32 possible values),
144 // remaining 11 for module ID inside det (2048 possible values).
146 layerId = VolUIDToLayer(fVolUID,modId);
149 //_____________________________________________________________________________
150 void AliAlignObj::AnglesToMatrix(const Double_t *angles, Double_t *rot) const
152 // Calculates the rotation matrix using the
153 // Euler angles in "x y z" notation
154 Double_t degrad = TMath::DegToRad();
155 Double_t sinpsi = TMath::Sin(degrad*angles[0]);
156 Double_t cospsi = TMath::Cos(degrad*angles[0]);
157 Double_t sinthe = TMath::Sin(degrad*angles[1]);
158 Double_t costhe = TMath::Cos(degrad*angles[1]);
159 Double_t sinphi = TMath::Sin(degrad*angles[2]);
160 Double_t cosphi = TMath::Cos(degrad*angles[2]);
162 rot[0] = costhe*cosphi;
163 rot[1] = -costhe*sinphi;
165 rot[3] = sinpsi*sinthe*cosphi + cospsi*sinphi;
166 rot[4] = -sinpsi*sinthe*sinphi + cospsi*cosphi;
167 rot[5] = -costhe*sinpsi;
168 rot[6] = -cospsi*sinthe*cosphi + sinpsi*sinphi;
169 rot[7] = cospsi*sinthe*sinphi + sinpsi*cosphi;
170 rot[8] = costhe*cospsi;
173 //_____________________________________________________________________________
174 Bool_t AliAlignObj::MatrixToAngles(const Double_t *rot, Double_t *angles) const
176 // Calculates the Euler angles in "x y z" notation
177 // using the rotation matrix
178 if(rot[0]<1e-7 || rot[8]<1e-7) return kFALSE;
179 Double_t raddeg = TMath::RadToDeg();
180 angles[0]=raddeg*TMath::ATan2(-rot[5],rot[8]);
181 angles[1]=raddeg*TMath::ASin(rot[2]);
182 angles[2]=raddeg*TMath::ATan2(-rot[1],rot[0]);
186 //______________________________________________________________________________
187 void AliAlignObj::Transform(AliTrackPoint &p) const
189 // The method transforms the space-point coordinates using the
190 // transformation matrix provided by the AliAlignObj
191 // The covariance matrix is not affected since we assume
192 // that the transformations are sufficiently small
194 if (fVolUID != p.GetVolumeID())
195 AliWarning(Form("Alignment object ID is not equal to the space-point ID (%d != %d)",fVolUID,p.GetVolumeID()));
199 Double_t *rot = m.GetRotationMatrix();
200 Double_t *tr = m.GetTranslation();
202 Float_t xyzin[3],xyzout[3];
204 for (Int_t i = 0; i < 3; i++)
213 //______________________________________________________________________________
214 void AliAlignObj::Transform(AliTrackPointArray &array) const
217 for (Int_t i = 0; i < array.GetNPoints(); i++) {
220 array.AddPoint(i,&p);
224 //_____________________________________________________________________________
225 void AliAlignObj::Print(Option_t *) const
227 // Print the contents of the
228 // alignment object in angles and
229 // matrix representations
236 const Double_t *rot = m.GetRotationMatrix();
237 // printf("Volume=%s ID=%u\n", GetVolPath(),GetVolUID());
240 GetVolUID(layerId,modId);
241 printf("Volume=%s LayerID=%d ModuleID=%d\n", GetVolPath(),layerId,modId);
242 printf("%12.6f%12.6f%12.6f Tx = %12.6f Psi = %12.6f\n", rot[0], rot[1], rot[2], tr[0], angles[0]);
243 printf("%12.6f%12.6f%12.6f Ty = %12.6f Theta = %12.6f\n", rot[3], rot[4], rot[5], tr[1], angles[1]);
244 printf("%12.6f%12.6f%12.6f Tz = %12.6f Phi = %12.6f\n", rot[6], rot[7], rot[8], tr[2], angles[2]);
248 //_____________________________________________________________________________
249 UShort_t AliAlignObj::LayerToVolUID(ELayerID layerId, Int_t modId)
251 // From detector (layer) name and module number (according to detector numbering)
252 // build fVolUID, unique numerical identity of that volume inside ALICE
253 // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
254 // remaining 11 for module ID inside det (2048 possible values).
256 return ((UShort_t(layerId) << 11) | UShort_t(modId));
259 //_____________________________________________________________________________
260 UShort_t AliAlignObj::LayerToVolUID(Int_t layerId, Int_t modId)
262 // From detector (layer) index and module number (according to detector numbering)
263 // build fVolUID, unique numerical identity of that volume inside ALICE
264 // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
265 // remaining 11 for module ID inside det (2048 possible values).
267 return ((UShort_t(layerId) << 11) | UShort_t(modId));
270 //_____________________________________________________________________________
271 AliAlignObj::ELayerID AliAlignObj::VolUIDToLayer(UShort_t voluid, Int_t &modId)
273 // From detector (layer) name and module number (according to detector numbering)
274 // build fVolUID, unique numerical identity of that volume inside ALICE
275 // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
276 // remaining 11 for module ID inside det (2048 possible values).
278 modId = voluid & 0x7ff;
280 return VolUIDToLayer(voluid);
283 //_____________________________________________________________________________
284 AliAlignObj::ELayerID AliAlignObj::VolUIDToLayer(UShort_t voluid)
286 // From detector (layer) name and module number (according to detector numbering)
287 // build fVolUID, unique numerical identity of that volume inside ALICE
288 // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
289 // remaining 11 for module ID inside det (2048 possible values).
291 return ELayerID((voluid >> 11) & 0x1f);
294 //_____________________________________________________________________________
295 Bool_t AliAlignObj::SetLocalPars(Double_t x, Double_t y, Double_t z,
296 Double_t psi, Double_t theta, Double_t phi)
298 // Set the translations and angles by using parameters
299 // defined in the local (in TGeo means) coordinate system
300 // of the alignable volume. In case that the TGeo was
301 // initialized, returns false and the object parameters are
303 if (!gGeoManager || !gGeoManager->IsClosed()) {
304 AliError("Can't set the alignment object parameters! gGeoManager doesn't exist or it is still opened!");
308 const char* volpath = GetVolPath();
309 TGeoPhysicalNode* node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(volpath);
311 AliError(Form("Volume path %s not valid!",volpath));
314 if (node->IsAligned())
315 AliWarning(Form("Volume %s has been already misaligned!",volpath));
319 tr[0]=x; tr[1]=y; tr[2]=z;
320 m.SetTranslation(tr);
321 Double_t angles[3] = {psi, theta, phi};
323 AnglesToMatrix(angles,rot);
326 TGeoHMatrix align,gprime,gprimeinv;
327 gprime = *node->GetMatrix();
328 gprimeinv = gprime.Inverse();
329 m.Multiply(&gprimeinv);
330 m.MultiplyLeft(&gprime);
337 //_____________________________________________________________________________
338 Bool_t AliAlignObj::ApplyToGeometry()
340 // Apply the current alignment object
341 // to the TGeo geometry
343 if (!gGeoManager || !gGeoManager->IsClosed()) {
344 AliError("Can't apply the alignment object! gGeoManager doesn't exist or it is still opened!");
348 const char* volpath = GetVolPath();
349 TGeoPhysicalNode* node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(volpath);
351 AliError(Form("Volume path %s not valid!",volpath));
354 if (node->IsAligned()) {
355 AliWarning(Form("Volume %s has been already misaligned!",volpath));
359 TGeoHMatrix align,gprime;
360 gprime = *node->GetMatrix();
362 gprime.MultiplyLeft(&align);
363 TGeoHMatrix *ginv = new TGeoHMatrix;
364 TGeoHMatrix *g = node->GetMatrix(node->GetLevel()-1);
365 *ginv = g->Inverse();
367 AliAlignObj::ELayerID layerId; // unique identity for volume in the alobj
368 Int_t modId; // unique identity for volume in the alobj
369 GetVolUID(layerId, modId);
370 AliInfo(Form("Aligning volume %s of detector layer %d with local ID %d",volpath,layerId,modId));
376 //_____________________________________________________________________________
377 Bool_t AliAlignObj::GetFromGeometry(const char *path, AliAlignObj &alobj)
379 // Get the alignment object which correspond
380 // to the TGeo volume defined by the 'path'.
381 // The method is extremely slow due to the
382 // searching by string. Therefore it should
383 // be used with great care!!
385 // Reset the alignment object
386 alobj.SetPars(0,0,0,0,0,0);
387 alobj.SetVolPath(path);
389 if (!gGeoManager || !gGeoManager->IsClosed()) {
390 AliErrorClass("Can't get the alignment object! gGeoManager doesn't exist or it is still opened!");
394 if (!gGeoManager->GetListOfPhysicalNodes()) {
395 AliErrorClass("Can't get the alignment object! gGeoManager doesn't contain any aligned nodes!");
399 TObjArray* nodesArr = gGeoManager->GetListOfPhysicalNodes();
400 TGeoPhysicalNode* node = NULL;
401 for (Int_t iNode = 0; iNode < nodesArr->GetEntriesFast(); iNode++) {
402 node = (TGeoPhysicalNode*) nodesArr->UncheckedAt(iNode);
403 const char *nodePath = node->GetName();
404 if (strcmp(path,nodePath) == 0) break;
407 AliWarningClass(Form("Volume path %s not found!",path));
411 TGeoHMatrix align,gprime,g,ginv,l;
412 gprime = *node->GetMatrix();
413 l = *node->GetOriginalMatrix();
414 g = *node->GetMatrix(node->GetLevel()-1);
417 align = gprime * ginv;
418 alobj.SetMatrix(align);
423 //_____________________________________________________________________________
424 const char* AliAlignObj::GetVolPath(ELayerID layerId, Int_t modId)
426 if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
427 AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
430 return fgVolPath[layerId-kFirstLayer][modId].Data();
433 //_____________________________________________________________________________
434 void AliAlignObj::InitVolPaths()
436 // Initialize the LUTs which contain
437 // the TGeo volume paths for each
438 // alignable volume. The LUTs are
439 // static, so they are created during
440 // the creation of the first intance
443 if (fgVolPath[0]) return;
445 for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++)
446 fgVolPath[iLayer] = new TString[fgLayerSize[iLayer]];
448 /********************* SPD layer1 ***********************/
451 TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT12_1/I12B_"; //".../I12A_"
452 TString str1 = "/I10B_"; //"/I10A_";
453 TString str2 = "/I107_"; //"/I103_"
454 // TString str3 = "/I101_1/ITS1_1";
455 TString volpath, volpath1, volpath2;
457 for(Int_t c1 = 1; c1<=10; c1++){
461 for(Int_t c2 =1; c2<=2; c2++){
465 for(Int_t c3 =1; c3<=4; c3++){
469 fgVolPath[kSPD1-kFirstLayer][modnum] = volpath2.Data();
476 /********************* SPD layer2 ***********************/
479 TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT12_1/I12B_"; //".../I12A_"
480 TString str1 = "/I20B_"; //"/I20A"
481 TString str2 = "/I1D7_"; //"/I1D3"
482 // TString str3 = "/I1D1_1/ITS2_1";
483 TString volpath, volpath1, volpath2;
485 for(Int_t c1 = 1; c1<=10; c1++){
489 for(Int_t c2 =1; c2<=4; c2++){
493 for(Int_t c3 =1; c3<=4; c3++){
497 fgVolPath[kSPD2-kFirstLayer][modnum] = volpath2.Data();
504 /********************* SDD layer1 ***********************/
507 TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT34_1/I004_";
508 TString str1 = "/I302_";
509 // TString str2 = "/ITS3_1";
510 TString volpath, volpath1;
512 for(Int_t c1 = 1; c1<=14; c1++){
516 for(Int_t c2 =1; c2<=6; c2++){
520 fgVolPath[kSDD1-kFirstLayer][modnum] = volpath1.Data();
526 /********************* SDD layer2 ***********************/
529 TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT34_1/I005_";
530 TString str1 = "/I402_";
531 // TString str2 = "/ITS4_1";
532 TString volpath, volpath1;
534 for(Int_t c1 = 1; c1<=22; c1++){
538 for(Int_t c2 = 1; c2<=8; c2++){
542 fgVolPath[kSDD2-kFirstLayer][modnum] = volpath1.Data();
548 /********************* SSD layer1 ***********************/
551 TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT56_1/I565_";
552 TString str1 = "/I562_";
553 // TString str2 = "/ITS5_1";
554 TString volpath, volpath1;
556 for(Int_t c1 = 1; c1<=34; c1++){
560 for(Int_t c2 = 1; c2<=22; c2++){
564 fgVolPath[kSSD1-kFirstLayer][modnum] = volpath1.Data();
570 /********************* SSD layer1 ***********************/
573 TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT56_1/I569_";
574 TString str1 = "/I566_";
575 // TString str2 = "/ITS6_1";
576 TString volpath, volpath1;
578 for(Int_t c1 = 1; c1<=38; c1++){
582 for(Int_t c2 = 1; c2<=25; c2++){
586 fgVolPath[kSSD2-kFirstLayer][modnum] = volpath1.Data();
592 /*************** TPC inner chambers' layer ****************/
595 TString str1 = "ALIC_1/TPC_M_1/TPC_Drift_1/TPC_ENDCAP_1/TPC_SECT_";
596 TString str2 = "ALIC_1/TPC_M_1/TPC_Drift_1/TPC_ENDCAP_2/TPC_SECT_";
597 TString str_in = "/TPC_IROC_1";
600 for(Int_t cnt=1; cnt<=18; cnt++){
604 fgVolPath[kTPC1-kFirstLayer][modnum] = volpath.Data();
607 for(Int_t cnt=1; cnt<=18; cnt++){
611 fgVolPath[kTPC1-kFirstLayer][modnum] = volpath.Data();
616 /*************** TPC outer chambers' layer ****************/
619 TString str1 = "ALIC_1/TPC_M_1/TPC_Drift_1/TPC_ENDCAP_1/TPC_SECT_";
620 TString str2 = "ALIC_1/TPC_M_1/TPC_Drift_1/TPC_ENDCAP_2/TPC_SECT_";
621 TString str_out = "/TPC_OROC_1";
624 for(Int_t cnt=1; cnt<=18; cnt++){
628 fgVolPath[kTPC2-kFirstLayer][modnum] = volpath.Data();
631 for(Int_t cnt=1; cnt<=18; cnt++){
635 fgVolPath[kTPC2-kFirstLayer][modnum] = volpath.Data();
640 /********************* TOF layer ***********************/
645 Int_t nStripSec=nstrA+2*nstrB+2*nstrC;
647 for (Int_t modnum=0; modnum < 1674; modnum++) {
649 Int_t sector = modnum/nStripSec;
657 sprintf(string1,"/ALIC_1/B077_1/B075_%i/BTO3_1",icopy);
661 sprintf(string1,"/ALIC_1/B077_1/B071_%i/BTO1_1",icopy);
663 else if(sector==11 || sector==12){
665 sprintf(string1,"/ALIC_1/B077_1/B074_%i/BTO2_1",icopy);
669 sprintf(string1,"/ALIC_1/B077_1/B071_%i/BTO1_1",icopy);
672 Int_t strInSec=modnum%nStripSec;
674 if( strInSec < nstrC){
675 icopy= nstrC - (strInSec+1) + 1;
676 sprintf(string2,"FTOC_1/FLTC_0/FSTR_%i",icopy);
678 else if(strInSec< nstrC+nstrB){
680 icopy= nstrB - (strInSec-nstrC+1) + 1;
681 sprintf(string2,"FTOB_1/FLTB_0/FSTR_%i",icopy);
684 else if(strInSec< nstrC+nstrB+nstrA){
686 icopy= strInSec-(nstrC+nstrB)+1;
687 sprintf(string2,"FTOA_0/FLTA_0/FSTR_%i",icopy);
689 else if(strInSec< nstrC+2*nstrB+nstrA){
691 icopy= strInSec-(nstrC+nstrB+nstrA)+1;
692 sprintf(string2,"FTOB_2/FLTB_0/FSTR_%i",icopy);
697 icopy= strInSec-(nstrC+2*nstrB+nstrA)+1;
698 sprintf(string2,"FTOC_2/FLTC_0/FSTR_%i",icopy);
703 sprintf(path,"%s/%s",string1,string2);
704 // printf("%d %s\n",modnum,path);
705 fgVolPath[kTOF-kFirstLayer][modnum] = path;
709 /********************* RICH layer ***********************/
711 TString str = "ALIC_1/RICH_";
714 for (Int_t modnum=0; modnum < 7; modnum++) {
716 volpath += (modnum+1);
717 fgVolPath[kRICH-kFirstLayer][modnum] = volpath.Data();