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::ApplyToGeometry()
297 // Apply the current alignment object
298 // to the TGeo geometry
300 if (!gGeoManager || !gGeoManager->IsClosed()) {
301 AliError("Can't apply the alignment object! gGeoManager doesn't exist or it is still opened!");
305 const char* volpath = GetVolPath();
306 TGeoPhysicalNode* node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(volpath);
308 AliError(Form("Volume path %s not valid!",volpath));
311 if (node->IsAligned()) {
312 AliWarning(Form("Volume %s has been already misaligned!",volpath));
316 TGeoHMatrix align,gprime;
317 gprime = *node->GetMatrix();
319 gprime.MultiplyLeft(&align);
320 TGeoHMatrix *ginv = new TGeoHMatrix;
321 TGeoHMatrix *g = node->GetMatrix(node->GetLevel()-1);
322 *ginv = g->Inverse();
324 AliAlignObj::ELayerID layerId; // unique identity for volume in the alobj
325 Int_t modId; // unique identity for volume in the alobj
326 GetVolUID(layerId, modId);
327 AliInfo(Form("Aligning volume %s of detector layer %d with local ID %d",volpath,layerId,modId));
333 //_____________________________________________________________________________
334 Bool_t AliAlignObj::GetFromGeometry(const char *path, AliAlignObj &alobj)
336 // Get the alignment object which correspond
337 // to the TGeo volume defined by the 'path'.
338 // The method is extremely slow due to the
339 // searching by string. Therefore it should
340 // be used with great care!!
342 // Reset the alignment object
343 alobj.SetPars(0,0,0,0,0,0);
344 alobj.SetVolPath(path);
346 if (!gGeoManager || !gGeoManager->IsClosed()) {
347 AliErrorClass("Can't get the alignment object! gGeoManager doesn't exist or it is still opened!");
351 if (!gGeoManager->GetListOfPhysicalNodes()) {
352 AliErrorClass("Can't get the alignment object! gGeoManager doesn't contain any aligned nodes!");
356 TObjArray* nodesArr = gGeoManager->GetListOfPhysicalNodes();
357 TGeoPhysicalNode* node = NULL;
358 for (Int_t iNode = 0; iNode < nodesArr->GetEntriesFast(); iNode++) {
359 node = (TGeoPhysicalNode*) nodesArr->UncheckedAt(iNode);
360 const char *nodePath = node->GetName();
361 if (strcmp(path,nodePath) == 0) break;
364 AliWarningClass(Form("Volume path %s not found!",path));
368 TGeoHMatrix align,gprime,g,ginv,l;
369 gprime = *node->GetMatrix();
370 l = *node->GetOriginalMatrix();
371 g = *node->GetMatrix(node->GetLevel()-1);
374 align = gprime * ginv;
375 alobj.SetMatrix(align);
380 //_____________________________________________________________________________
381 const char* AliAlignObj::GetVolPath(ELayerID layerId, Int_t modId)
383 if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
384 AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
387 return fgVolPath[layerId-kFirstLayer][modId].Data();
390 //_____________________________________________________________________________
391 void AliAlignObj::InitVolPaths()
393 // Initialize the LUTs which contain
394 // the TGeo volume paths for each
395 // alignable volume. The LUTs are
396 // static, so they are created during
397 // the creation of the first intance
400 if (fgVolPath[0]) return;
402 for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++)
403 fgVolPath[iLayer] = new TString[fgLayerSize[iLayer]];
405 /********************* SPD layer1 ***********************/
408 TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT12_1/I12B_"; //".../I12A_"
409 TString str1 = "/I10B_"; //"/I10A_";
410 TString str2 = "/I107_"; //"/I103_"
411 // TString str3 = "/I101_1/ITS1_1";
412 TString volpath, volpath1, volpath2;
414 for(Int_t c1 = 1; c1<=10; c1++){
418 for(Int_t c2 =1; c2<=2; c2++){
422 for(Int_t c3 =1; c3<=4; c3++){
426 fgVolPath[kSPD1-kFirstLayer][modnum] = volpath2.Data();
433 /********************* SPD layer2 ***********************/
436 TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT12_1/I12B_"; //".../I12A_"
437 TString str1 = "/I20B_"; //"/I20A"
438 TString str2 = "/I1D7_"; //"/I1D3"
439 // TString str3 = "/I1D1_1/ITS2_1";
440 TString volpath, volpath1, volpath2;
442 for(Int_t c1 = 1; c1<=10; c1++){
446 for(Int_t c2 =1; c2<=4; c2++){
450 for(Int_t c3 =1; c3<=4; c3++){
454 fgVolPath[kSPD2-kFirstLayer][modnum] = volpath2.Data();
461 /********************* SDD layer1 ***********************/
464 TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT34_1/I004_";
465 TString str1 = "/I302_";
466 // TString str2 = "/ITS3_1";
467 TString volpath, volpath1;
469 for(Int_t c1 = 1; c1<=14; c1++){
473 for(Int_t c2 =1; c2<=6; c2++){
477 fgVolPath[kSDD1-kFirstLayer][modnum] = volpath1.Data();
483 /********************* SDD layer2 ***********************/
486 TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT34_1/I005_";
487 TString str1 = "/I402_";
488 // TString str2 = "/ITS4_1";
489 TString volpath, volpath1;
491 for(Int_t c1 = 1; c1<=22; c1++){
495 for(Int_t c2 = 1; c2<=8; c2++){
499 fgVolPath[kSDD2-kFirstLayer][modnum] = volpath1.Data();
505 /********************* SSD layer1 ***********************/
508 TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT56_1/I565_";
509 TString str1 = "/I562_";
510 // TString str2 = "/ITS5_1";
511 TString volpath, volpath1;
513 for(Int_t c1 = 1; c1<=34; c1++){
517 for(Int_t c2 = 1; c2<=22; c2++){
521 fgVolPath[kSSD1-kFirstLayer][modnum] = volpath1.Data();
527 /********************* SSD layer1 ***********************/
530 TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT56_1/I569_";
531 TString str1 = "/I566_";
532 // TString str2 = "/ITS6_1";
533 TString volpath, volpath1;
535 for(Int_t c1 = 1; c1<=38; c1++){
539 for(Int_t c2 = 1; c2<=25; c2++){
543 fgVolPath[kSSD2-kFirstLayer][modnum] = volpath1.Data();
549 /*************** TPC inner chambers' layer ****************/
552 TString str1 = "ALIC_1/TPC_M_1/TPC_Drift_1/TPC_ENDCAP_1/TPC_SECT_";
553 TString str2 = "ALIC_1/TPC_M_1/TPC_Drift_1/TPC_ENDCAP_2/TPC_SECT_";
554 TString str_in = "/TPC_IROC_1";
557 for(Int_t cnt=1; cnt<=18; cnt++){
561 fgVolPath[kTPC1-kFirstLayer][modnum] = volpath.Data();
564 for(Int_t cnt=1; cnt<=18; cnt++){
568 fgVolPath[kTPC1-kFirstLayer][modnum] = volpath.Data();
573 /*************** TPC outer chambers' layer ****************/
576 TString str1 = "ALIC_1/TPC_M_1/TPC_Drift_1/TPC_ENDCAP_1/TPC_SECT_";
577 TString str2 = "ALIC_1/TPC_M_1/TPC_Drift_1/TPC_ENDCAP_2/TPC_SECT_";
578 TString str_out = "/TPC_OROC_1";
581 for(Int_t cnt=1; cnt<=18; cnt++){
585 fgVolPath[kTPC2-kFirstLayer][modnum] = volpath.Data();
588 for(Int_t cnt=1; cnt<=18; cnt++){
592 fgVolPath[kTPC2-kFirstLayer][modnum] = volpath.Data();
597 /********************* TOF layer ***********************/
602 Int_t nStripSec=nstrA+2*nstrB+2*nstrC;
604 for (Int_t modnum=0; modnum < 1674; modnum++) {
606 Int_t sector = modnum/nStripSec;
614 sprintf(string1,"/ALIC_1/B077_1/B075_%i/BTO3_1",icopy);
618 sprintf(string1,"/ALIC_1/B077_1/B071_%i/BTO1_1",icopy);
620 else if(sector==11 || sector==12){
622 sprintf(string1,"/ALIC_1/B077_1/B074_%i/BTO2_1",icopy);
626 sprintf(string1,"/ALIC_1/B077_1/B071_%i/BTO1_1",icopy);
629 Int_t strInSec=modnum%nStripSec;
631 if( strInSec < nstrC){
632 icopy= nstrC - (strInSec+1) + 1;
633 sprintf(string2,"FTOC_1/FLTC_0/FSTR_%i",icopy);
635 else if(strInSec< nstrC+nstrB){
637 icopy= nstrB - (strInSec-nstrC+1) + 1;
638 sprintf(string2,"FTOB_1/FLTB_0/FSTR_%i",icopy);
641 else if(strInSec< nstrC+nstrB+nstrA){
643 icopy= strInSec-(nstrC+nstrB)+1;
644 sprintf(string2,"FTOA_0/FLTA_0/FSTR_%i",icopy);
646 else if(strInSec< nstrC+2*nstrB+nstrA){
648 icopy= strInSec-(nstrC+nstrB+nstrA)+1;
649 sprintf(string2,"FTOB_2/FLTB_0/FSTR_%i",icopy);
654 icopy= strInSec-(nstrC+2*nstrB+nstrA)+1;
655 sprintf(string2,"FTOC_2/FLTC_0/FSTR_%i",icopy);
660 sprintf(path,"%s/%s",string1,string2);
661 // printf("%d %s\n",modnum,path);
662 fgVolPath[kTOF-kFirstLayer][modnum] = path;
666 /********************* RICH layer ***********************/
668 TString str = "ALIC_1/RICH_";
671 for (Int_t modnum=0; modnum < 7; modnum++) {
673 volpath += (modnum+1);
674 fgVolPath[kRICH-kFirstLayer][modnum] = volpath.Data();