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()
112 //_____________________________________________________________________________
113 void AliAlignObj::SetVolUID(ELayerID detId, Int_t modId)
115 // From detector name and module number (according to detector numbering)
116 // build fVolUID, unique numerical identity of that volume inside ALICE
117 // fVolUID is 16 bits, first 5 reserved for detID (32 possible values),
118 // remaining 11 for module ID inside det (2048 possible values).
120 fVolUID = LayerToVolUID(detId,modId);
123 //_____________________________________________________________________________
124 void AliAlignObj::GetVolUID(ELayerID &layerId, Int_t &modId) const
126 // From detector name and module number (according to detector numbering)
127 // build fVolUID, unique numerical identity of that volume inside ALICE
128 // fVolUID is 16 bits, first 5 reserved for detID (32 possible values),
129 // remaining 11 for module ID inside det (2048 possible values).
131 layerId = VolUIDToLayer(fVolUID,modId);
134 //_____________________________________________________________________________
135 void AliAlignObj::AnglesToMatrix(const Double_t *angles, Double_t *rot) const
137 // Calculates the rotation matrix using the
138 // Euler angles in "x y z" notation
139 Double_t degrad = TMath::DegToRad();
140 Double_t sinpsi = TMath::Sin(degrad*angles[0]);
141 Double_t cospsi = TMath::Cos(degrad*angles[0]);
142 Double_t sinthe = TMath::Sin(degrad*angles[1]);
143 Double_t costhe = TMath::Cos(degrad*angles[1]);
144 Double_t sinphi = TMath::Sin(degrad*angles[2]);
145 Double_t cosphi = TMath::Cos(degrad*angles[2]);
147 rot[0] = costhe*cosphi;
148 rot[1] = -costhe*sinphi;
150 rot[3] = sinpsi*sinthe*cosphi + cospsi*sinphi;
151 rot[4] = -sinpsi*sinthe*sinphi + cospsi*cosphi;
152 rot[5] = -costhe*sinpsi;
153 rot[6] = -cospsi*sinthe*cosphi + sinpsi*sinphi;
154 rot[7] = cospsi*sinthe*sinphi + sinpsi*cosphi;
155 rot[8] = costhe*cospsi;
158 //_____________________________________________________________________________
159 Bool_t AliAlignObj::MatrixToAngles(const Double_t *rot, Double_t *angles) const
161 // Calculates the Euler angles in "x y z" notation
162 // using the rotation matrix
163 if(rot[0]<1e-7 || rot[8]<1e-7) return kFALSE;
164 Double_t raddeg = TMath::RadToDeg();
165 angles[0]=raddeg*TMath::ATan2(-rot[5],rot[8]);
166 angles[1]=raddeg*TMath::ASin(rot[2]);
167 angles[2]=raddeg*TMath::ATan2(-rot[1],rot[0]);
171 //______________________________________________________________________________
172 void AliAlignObj::Transform(AliTrackPoint &p) const
174 // The method transforms the space-point coordinates using the
175 // transformation matrix provided by the AliAlignObj
176 // The covariance matrix is not affected since we assume
177 // that the transformations are sufficiently small
179 if (fVolUID != p.GetVolumeID())
180 AliWarning(Form("Alignment object ID is not equal to the space-point ID (%d != %d)",fVolUID,p.GetVolumeID()));
184 Double_t *rot = m.GetRotationMatrix();
185 Double_t *tr = m.GetTranslation();
187 Float_t xyzin[3],xyzout[3];
189 for (Int_t i = 0; i < 3; i++)
198 //______________________________________________________________________________
199 void AliAlignObj::Transform(AliTrackPointArray &array) const
202 for (Int_t i = 0; i < array.GetNPoints(); i++) {
205 array.AddPoint(i,&p);
209 //_____________________________________________________________________________
210 void AliAlignObj::Print(Option_t *) const
212 // Print the contents of the
213 // alignment object in angles and
214 // matrix representations
221 const Double_t *rot = m.GetRotationMatrix();
222 // printf("Volume=%s ID=%u\n", GetVolPath(),GetVolUID());
225 GetVolUID(layerId,modId);
226 printf("Volume=%s LayerID=%d ModuleID=%d\n", GetVolPath(),layerId,modId);
227 printf("%12.6f%12.6f%12.6f Tx = %12.6f Psi = %12.6f\n", rot[0], rot[1], rot[2], tr[0], angles[0]);
228 printf("%12.6f%12.6f%12.6f Ty = %12.6f Theta = %12.6f\n", rot[3], rot[4], rot[5], tr[1], angles[1]);
229 printf("%12.6f%12.6f%12.6f Tz = %12.6f Phi = %12.6f\n", rot[6], rot[7], rot[8], tr[2], angles[2]);
233 //_____________________________________________________________________________
234 UShort_t AliAlignObj::LayerToVolUID(ELayerID layerId, Int_t modId)
236 // From detector (layer) name and module number (according to detector numbering)
237 // build fVolUID, unique numerical identity of that volume inside ALICE
238 // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
239 // remaining 11 for module ID inside det (2048 possible values).
241 return ((UShort_t(layerId) << 11) | UShort_t(modId));
244 //_____________________________________________________________________________
245 AliAlignObj::ELayerID AliAlignObj::VolUIDToLayer(UShort_t voluid, Int_t &modId)
247 // From detector (layer) name and module number (according to detector numbering)
248 // build fVolUID, unique numerical identity of that volume inside ALICE
249 // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
250 // remaining 11 for module ID inside det (2048 possible values).
252 modId = voluid & 0x7ff;
254 return VolUIDToLayer(voluid);
257 //_____________________________________________________________________________
258 AliAlignObj::ELayerID AliAlignObj::VolUIDToLayer(UShort_t voluid)
260 // From detector (layer) name and module number (according to detector numbering)
261 // build fVolUID, unique numerical identity of that volume inside ALICE
262 // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
263 // remaining 11 for module ID inside det (2048 possible values).
265 return ELayerID((voluid >> 11) & 0x1f);
268 //_____________________________________________________________________________
269 Bool_t AliAlignObj::ApplyToGeometry()
271 // Apply the current alignment object
272 // to the TGeo geometry
274 if (!gGeoManager || !gGeoManager->IsClosed()) {
275 AliError("Can't apply the alignment object! gGeoManager doesn't exist or it is still opened!");
279 const char* volpath = GetVolPath();
280 TGeoPhysicalNode* node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(volpath);
282 AliError(Form("Volume path %s not valid!",volpath));
285 if (node->IsAligned()) {
286 AliWarning(Form("Volume %s has been already misaligned!",volpath));
290 TGeoHMatrix align,gprime;
291 gprime = *node->GetMatrix();
293 gprime.MultiplyLeft(&align);
294 TGeoHMatrix *ginv = new TGeoHMatrix;
295 TGeoHMatrix *g = node->GetMatrix(node->GetLevel()-1);
296 *ginv = g->Inverse();
298 AliAlignObj::ELayerID layerId; // unique identity for volume in the alobj
299 Int_t modId; // unique identity for volume in the alobj
300 GetVolUID(layerId, modId);
301 AliInfo(Form("Aligning volume %s of detector layer %d with local ID %d",volpath,layerId,modId));
307 //_____________________________________________________________________________
308 Bool_t AliAlignObj::GetFromGeometry(const char *path, AliAlignObj &alobj)
310 // Get the alignment object which correspond
311 // to the TGeo volume defined by the 'path'.
312 // The method is extremely slow due to the
313 // searching by string. Therefore it should
314 // be used with great care!!
316 // Reset the alignment object
317 alobj.SetPars(0,0,0,0,0,0);
318 alobj.SetVolPath(path);
320 if (!gGeoManager || !gGeoManager->IsClosed()) {
321 AliErrorClass("Can't get the alignment object! gGeoManager doesn't exist or it is still opened!");
325 if (!gGeoManager->GetListOfPhysicalNodes()) {
326 AliErrorClass("Can't get the alignment object! gGeoManager doesn't contain any aligned nodes!");
330 TObjArray* nodesArr = gGeoManager->GetListOfPhysicalNodes();
331 TGeoPhysicalNode* node = NULL;
332 for (Int_t iNode = 0; iNode < nodesArr->GetEntriesFast(); iNode++) {
333 node = (TGeoPhysicalNode*) nodesArr->UncheckedAt(iNode);
334 const char *nodePath = node->GetName();
335 if (strcmp(path,nodePath) == 0) break;
338 AliWarningClass(Form("Volume path %s not found!",path));
342 TGeoHMatrix align,gprime,g,ginv,l;
343 gprime = *node->GetMatrix();
344 l = *node->GetOriginalMatrix();
345 g = *node->GetMatrix(node->GetLevel()-1);
348 align = gprime * ginv;
349 alobj.SetMatrix(align);
354 //_____________________________________________________________________________
355 void AliAlignObj::InitVolPaths()
357 // Initialize the LUTs which contain
358 // the TGeo volume paths for each
359 // alignable volume. The LUTs are
360 // static, so they are created during
361 // the creation of the first intance
364 if (fgVolPath[0]) return;
366 for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++)
367 fgVolPath[iLayer] = new TString[fgLayerSize[iLayer]];
369 /********************* SPD layer1 ***********************/
372 TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT12_1/I12B_"; //".../I12A_"
373 TString str1 = "/I10B_"; //"/I10A_";
374 TString str2 = "/I107_"; //"/I103_"
375 // TString str3 = "/I101_1/ITS1_1";
376 TString volpath, volpath1, volpath2;
378 for(Int_t c1 = 1; c1<=10; c1++){
382 for(Int_t c2 =1; c2<=2; c2++){
386 for(Int_t c3 =1; c3<=4; c3++){
390 fgVolPath[kSPD1-kFirstLayer][modnum] = volpath2.Data();
397 /********************* SPD layer2 ***********************/
400 TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT12_1/I12B_"; //".../I12A_"
401 TString str1 = "/I20B_"; //"/I20A"
402 TString str2 = "/I1D7_"; //"/I1D3"
403 // TString str3 = "/I1D1_1/ITS2_1";
404 TString volpath, volpath1, volpath2;
406 for(Int_t c1 = 1; c1<=10; c1++){
410 for(Int_t c2 =1; c2<=4; c2++){
414 for(Int_t c3 =1; c3<=4; c3++){
418 fgVolPath[kSPD2-kFirstLayer][modnum] = volpath2.Data();
425 /********************* SDD layer1 ***********************/
428 TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT34_1/I004_";
429 TString str1 = "/I302_";
430 // TString str2 = "/ITS3_1";
431 TString volpath, volpath1;
433 for(Int_t c1 = 1; c1<=14; c1++){
437 for(Int_t c2 =1; c2<=6; c2++){
441 fgVolPath[kSDD1-kFirstLayer][modnum] = volpath1.Data();
447 /********************* SDD layer2 ***********************/
450 TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT34_1/I005_";
451 TString str1 = "/I402_";
452 // TString str2 = "/ITS4_1";
453 TString volpath, volpath1;
455 for(Int_t c1 = 1; c1<=22; c1++){
459 for(Int_t c2 = 1; c2<=8; c2++){
463 fgVolPath[kSDD2-kFirstLayer][modnum] = volpath1.Data();
469 /********************* SSD layer1 ***********************/
472 TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT56_1/I565_";
473 TString str1 = "/I562_";
474 // TString str2 = "/ITS5_1";
475 TString volpath, volpath1;
477 for(Int_t c1 = 1; c1<=34; c1++){
481 for(Int_t c2 = 1; c2<=22; c2++){
485 fgVolPath[kSSD1-kFirstLayer][modnum] = volpath1.Data();
491 /********************* SSD layer1 ***********************/
494 TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT56_1/I569_";
495 TString str1 = "/I566_";
496 // TString str2 = "/ITS6_1";
497 TString volpath, volpath1;
499 for(Int_t c1 = 1; c1<=38; c1++){
503 for(Int_t c2 = 1; c2<=25; c2++){
507 fgVolPath[kSSD2-kFirstLayer][modnum] = volpath1.Data();
513 /********************* TOF layer ***********************/
518 Int_t nStripSec=nstrA+2*nstrB+2*nstrC;
520 for (Int_t modnum=0; modnum < 1674; modnum++) {
522 Int_t sector = modnum/nStripSec;
530 sprintf(string1,"/ALIC_1/B077_1/B075_%i/BTO3_1",icopy);
534 sprintf(string1,"/ALIC_1/B077_1/B071_%i/BTO1_1",icopy);
536 else if(sector==11 || sector==12){
538 sprintf(string1,"/ALIC_1/B077_1/B074_%i/BTO2_1",icopy);
542 sprintf(string1,"/ALIC_1/B077_1/B071_%i/BTO1_1",icopy);
545 Int_t strInSec=modnum%nStripSec;
547 if( strInSec < nstrC){
549 sprintf(string2,"FTOC_1/FLTC_1/FSTR_%i",icopy);
551 else if(strInSec< nstrC+nstrB){
553 icopy= strInSec-nstrC+1;
554 sprintf(string2,"FTOB_1/FLTB_1/FSTR_%i",icopy);
557 else if(strInSec< nstrC+nstrB+nstrA){
559 icopy= strInSec-(nstrC+nstrB)+1;
560 sprintf(string2,"FTOA_1/FLTA_1/FSTR_%i",icopy);
563 else if(strInSec< nstrC+2*nstrB+nstrA){
565 icopy= strInSec-(nstrC+nstrB+nstrA)+1;
566 sprintf(string2,"FTOB_2/FLTB_2/FSTR_%i",icopy);
571 icopy= strInSec-(nstrC+2*nstrB+nstrA)+1;
572 sprintf(string2,"FTOC_2/FLTC_2/FSTR_%i",icopy);
577 sprintf(path,"%s/%s",string1,string2);
578 // printf("%d %s\n",modnum,path);
579 fgVolPath[kTOF-kFirstLayer][modnum] = path;