Project
Loading...
Searching...
No Matches
AlignParam.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
14
15#include <TGeoManager.h>
16#include <TGeoMatrix.h>
17#include <TGeoOverlap.h>
18#include <TGeoPhysicalNode.h>
19
20#include "Framework/Logger.h"
22
23using namespace o2::detectors;
24
25//___________________________________________________
26AlignParam::AlignParam(const char* symname, int algID, // volume symbolic name and its alignable ID
27 double x, double y, double z, // delta translation
28 double psi, double theta, double phi, // delta rotation
29 bool global, // global (preferable) or local delta definition
30 bool convertLocalToGlobal) // if local is provided, convert it to global
31 : mSymName(symname), mIsGlobal(global || convertLocalToGlobal), mAlignableID(algID)
32{
38
39 setParams(x, y, z, psi, theta, phi);
40 if (!global && convertLocalToGlobal) {
41 setLocalParams(x, y, z, psi, theta, phi);
42 }
43}
44
45//___________________________________________________
46AlignParam::AlignParam(const char* symname, int algID, TGeoMatrix& m, bool global, bool convertLocalToGlobal)
47 : mSymName(symname), mIsGlobal(global || convertLocalToGlobal), mAlignableID(algID)
48{
50 if (!setRotation(m)) {
51 const double* rot = m.GetRotationMatrix();
52 throw std::runtime_error(fmt::format("Failed to extract roll-pitch-yall angles from [[{},{},{}], [{},{},{}], [{},{},{}] for {}", rot[0], rot[1], rot[2], rot[3], rot[4], rot[5], rot[6], rot[7], rot[8], symname));
53 }
54 if (!global && convertLocalToGlobal && !setLocalParams(mX, mY, mZ, mPsi, mTheta, mPhi)) {
55 throw std::runtime_error(fmt::format("Alignment creation for {} failed: geomManager is absent", symname));
56 }
57}
58
59//___________________________________________________
60TGeoHMatrix AlignParam::createMatrix() const
61{
63 TGeoHMatrix mat;
64 setMatrixTranslation(mX, mY, mZ, mat);
65 setMatrixRotation(mPsi, mTheta, mPhi, mat);
66 return mat;
67}
68
69//___________________________________________________
70void AlignParam::setMatrixRotation(double psi, double theta, double phi, TGeoHMatrix& dest) const
71{
73 double rot[9] = {};
74 anglesToMatrix(psi, theta, phi, rot);
75 dest.SetRotation(rot);
76}
77
78//_____________________________________________________________________________
79void AlignParam::setTranslation(const TGeoMatrix& m)
80{
83
84 if (m.IsTranslation()) {
85 const double* tr = m.GetTranslation();
86 mX = tr[0];
87 mY = tr[1];
88 mZ = tr[2];
89 } else {
90 mX = mY = mZ = 0.;
91 }
92}
93
94//_____________________________________________________________________________
95bool AlignParam::setRotation(const TGeoMatrix& m)
96{
99
100 if (m.IsRotation()) {
101 const double* rot = m.GetRotationMatrix();
102 double psi, theta, phi;
103 if (!matrixToAngles(rot, psi, theta, phi)) {
104 return false;
105 }
106 setRotation(psi, theta, phi);
107 } else {
108 mPsi = mTheta = mPhi = 0.;
109 }
110 return true;
111}
112
113//_____________________________________________________________________________
114bool AlignParam::matrixToAngles(const double* rot, double& psi, double& theta, double& phi) const
115{
120 //
121 if (std::abs(rot[0]) < 1e-7 || std::abs(rot[8]) < 1e-7) {
122 LOG(error) << "Failed to extract roll-pitch-yall angles!";
123 return false;
124 }
125 psi = std::atan2(-rot[5], rot[8]);
126 theta = std::asin(rot[2]);
127 phi = std::atan2(-rot[1], rot[0]);
128 return true;
129}
130
131//_____________________________________________________________________________
132void AlignParam::anglesToMatrix(double psi, double theta, double phi, double* rot) const
133{
134 // Calculates the rotation matrix using the
135 // Euler angles in "x y z" notation
136 //
137 double sinpsi = std::sin(psi);
138 double cospsi = std::cos(psi);
139 double sinthe = std::sin(theta);
140 double costhe = std::cos(theta);
141 double sinphi = std::sin(phi);
142 double cosphi = std::cos(phi);
143
144 rot[0] = costhe * cosphi;
145 rot[1] = -costhe * sinphi;
146 rot[2] = sinthe;
147 rot[3] = sinpsi * sinthe * cosphi + cospsi * sinphi;
148 rot[4] = -sinpsi * sinthe * sinphi + cospsi * cosphi;
149 rot[5] = -costhe * sinpsi;
150 rot[6] = -cospsi * sinthe * cosphi + sinpsi * sinphi;
151 rot[7] = cospsi * sinthe * sinphi + sinpsi * cosphi;
152 rot[8] = costhe * cospsi;
153}
154
155//_____________________________________________________________________________
156bool AlignParam::setLocalParams(double x, double y, double z, double psi, double theta, double phi)
157{
162
163 TGeoHMatrix m;
164 double tr[3] = {x, y, z};
165 m.SetTranslation(tr);
166 setMatrixRotation(psi, theta, phi, m);
167 return setLocalParams(m);
168}
169
170//_____________________________________________________________________________
171bool AlignParam::setLocalParams(const TGeoMatrix& m)
172{
173 // Set the global delta transformation by passing the TGeo matrix
174 // for the local delta transformation.
175 // In case that the TGeo was not initialized or not closed,
176 // returns false and the object parameters are not set.
177 //
178 if (!gGeoManager || !gGeoManager->IsClosed()) {
179 LOG(error) << "Can't set the local alignment object parameters! gGeoManager doesn't exist or it is still open!";
180 return false;
181 }
182
183 const char* symname = getSymName().c_str();
184 TGeoHMatrix gprime, gprimeinv;
185 TGeoPhysicalNode* pn = nullptr;
186 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
187 if (pne) {
188 pn = pne->GetPhysicalNode();
189 if (pn) {
190 if (pn->IsAligned()) {
191 LOG(warning) << "Volume " << symname << " has been misaligned already!";
192 }
193 gprime = *pn->GetMatrix();
194 } else {
195 gprime = pne->GetGlobalOrig();
196 }
197 } else {
198 LOG(warning) << "The symbolic volume name " << symname
199 << " does not correspond to a physical entry. Using it as volume path!";
200 if (!gGeoManager->cd(symname)) {
201 LOG(error) << "Volume name or path " << symname << " is not valid!";
202 return false;
203 }
204 gprime = *gGeoManager->GetCurrentMatrix();
205 }
206
207 TGeoHMatrix m1; // the TGeoHMatrix copy of the local delta "m"
208 m1.SetTranslation(m.GetTranslation());
209 m1.SetRotation(m.GetRotationMatrix());
210
211 gprimeinv = gprime.Inverse();
212 m1.Multiply(&gprimeinv);
213 m1.MultiplyLeft(&gprime);
214
215 setGlobalParams(m1);
216 return true;
217}
218
219//_____________________________________________________________________________
220bool AlignParam::createLocalMatrix(TGeoHMatrix& m) const
221{
222 // Get the matrix for the local delta transformation.
223 // In case that the TGeo was not initialized or not closed,
224 // returns false and the object parameters are not set.
225 //
226 m = createMatrix();
227 if (!mIsGlobal) {
228 return true;
229 }
230 if (!gGeoManager || !gGeoManager->IsClosed()) {
231 LOG(error) << "Can't get the local alignment object parameters! gGeoManager doesn't exist or it is still open!";
232 return false;
233 }
234
235 const char* symname = getSymName().c_str();
236 TGeoPhysicalNode* node;
237 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
238 if (pne) {
239 if (!pne->GetPhysicalNode()) {
240 node = gGeoManager->MakeAlignablePN(pne);
241 } else {
242 node = pne->GetPhysicalNode();
243 }
244 } else {
245 LOG(warning) << "The symbolic volume name " << symname
246 << " does not correspond to a physical entry. Using it as volume path!";
247 node = (TGeoPhysicalNode*)gGeoManager->MakePhysicalNode(symname);
248 }
249
250 if (!node) {
251 LOG(error) << "Volume name or path " << symname << " is not valid!";
252 return false;
253 }
254 TGeoHMatrix gprime, gprimeinv;
255 gprime = *node->GetMatrix();
256 gprimeinv = gprime.Inverse();
257 m.Multiply(&gprime);
258 m.MultiplyLeft(&gprimeinv);
259
260 return true;
261}
262
263//_____________________________________________________________________________
264bool AlignParam::applyToGeometry(int printLevel) const
265{
269 //
270 if (!gGeoManager || !gGeoManager->IsClosed()) {
271 LOG(error) << "Can't apply the alignment object! gGeoManager doesn't exist or it is still open!";
272 return false;
273 }
274
275 if (gGeoManager->IsLocked()) {
276 LOG(error) << "Can't apply the alignment object! Geometry is locked!";
277 return false;
278 }
279
280 const char* symname = getSymName().c_str();
281 const char* path;
282 TGeoPhysicalNode* node;
283 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
284 if (pne) {
285 path = pne->GetTitle();
286 node = gGeoManager->MakeAlignablePN(pne);
287 } else {
288 LOG(debug) << "The symbolic volume name " << symname
289 << " does not correspond to a physical entry. Using it as a volume path!";
290 path = symname;
291 if (!gGeoManager->CheckPath(path)) {
292 LOG(error) << "Volume path " << path << " is not valid";
293 return false;
294 }
295 if (gGeoManager->GetListOfPhysicalNodes()->FindObject(path)) {
296 LOG(error) << "Volume path " << path << " has been misaligned already!";
297 return false;
298 }
299 node = (TGeoPhysicalNode*)gGeoManager->MakePhysicalNode(path);
300 }
301
302 if (!node) {
303 LOG(error) << "Volume path " << path << " is not valid";
304 return false;
305 }
306
307 // double threshold = 0.001;
308 TGeoHMatrix* align = new TGeoHMatrix(createMatrix());
309 if (mIsGlobal) {
310 align->Multiply(node->GetMatrix());
311 align->MultiplyLeft(node->GetMatrix(node->GetLevel() - 1)->Inverse());
312 } else {
313 align->MultiplyLeft(node->GetOriginalMatrix());
314 }
315
316 node->Align(align);
317
318 if (getLevel() <= printLevel) {
319 LOGP(info, "{:*^100}", symname);
320 LOGP(info, " - Alignment parameter:");
321 print();
322 LOGP(info, " - Alignment matrix:");
323 align->Print();
324 LOGP(info, " - Node:");
325 node->Print();
326 LOGP(info, "{:~^100}", symname);
327 }
328
329 return true;
330}
331
332//_____________________________________________________________________________
334{
338 //
339 if (!gGeoManager) {
340 LOG(error) << "gGeoManager doesn't exist or it is still open: unable to return meaningful level value.";
341 return -1;
342 }
343 const char* symname = getSymName().c_str();
344 const char* path;
345 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
346 if (pne) {
347 path = pne->GetTitle();
348 } else {
349 path = symname;
350 }
351
352 TString pathStr = path;
353 int lev = pathStr.CountChar('/');
354 return (pathStr[0] != '/') ? ++lev : lev;
355}
356
357//_____________________________________________________________________________
359{
360 // print parameters
361 printf("%s (Lvl:%2d): %6d | %s | tra: X: %+e Y: %+e Z: %+e | pitch: %+e roll: %+e yaw: %e\n", getSymName().c_str(), getLevel(), getAlignableID(), (mIsGlobal) ? "G" : "L",
362 getX(), getY(), getZ(), getPsi(), getTheta(), getPhi());
363}
364
365//_____________________________________________________________________________
366void AlignParam::setGlobalParams(double x, double y, double z, double psi, double theta, double phi)
367{
369 setTranslation(x, y, z);
370 setRotation(psi, theta, phi);
371}
372
373//_____________________________________________________________________________
374void AlignParam::setParams(double x, double y, double z, double psi, double theta, double phi)
375{
377 setTranslation(x, y, z);
378 setRotation(psi, theta, phi);
379}
380
381//_____________________________________________________________________________
382void AlignParam::setRotation(double psi, double theta, double phi)
383{
385 mPsi = psi;
386 mTheta = theta;
387 mPhi = phi;
388}
389
390//_____________________________________________________________________________
391void AlignParam::setTranslation(double x, double y, double z)
392{
394 mX = x;
395 mY = y;
396 mZ = z;
397}
398
399//_____________________________________________________________________________
400void AlignParam::setGlobalParams(const TGeoMatrix& m)
401{
404 setRotation(m);
405}
406
407//___________________________________________________
408void AlignParam::setMatrixTranslation(double x, double y, double z, TGeoHMatrix& dest) const
409{
411 double tra[3] = {x, y, z};
412 dest.SetTranslation(tra);
413}
414
415//_____________________________________________________________________________
416bool AlignParam::setLocalTranslation(double x, double y, double z)
417{
423
424 TGeoHMatrix m;
425 double tr[3] = {x, y, z};
426 m.SetTranslation(tr);
427
428 return setLocalParams(m);
429}
430
431//_____________________________________________________________________________
432bool AlignParam::setLocalTranslation(const TGeoMatrix& m)
433{
438
439 TGeoHMatrix mtr;
440 mtr.SetTranslation(m.GetTranslation());
441 return setLocalParams(mtr);
442}
443
444//_____________________________________________________________________________
445bool AlignParam::setLocalRotation(double psi, double theta, double phi)
446{
452
453 TGeoHMatrix m;
454 setMatrixRotation(psi, theta, phi, m);
455 return setLocalParams(m);
456}
457
458//_____________________________________________________________________________
459bool AlignParam::setLocalRotation(const TGeoMatrix& m)
460{
465
466 TGeoHMatrix rotm;
467 rotm.SetRotation(m.GetRotationMatrix());
468 return setLocalParams(rotm);
469}
470
471//_____________________________________________________________________________
472int AlignParam::rectify(double zero)
473{
474 int nonZero = 6;
475 if (std::abs(mX) < zero) {
476 mX = 0.;
477 }
478 if (std::abs(mY) < zero) {
479 mY = 0.;
480 nonZero--;
481 }
482 if (std::abs(mZ) < zero) {
483 mZ = 0.;
484 nonZero--;
485 }
486 if (std::abs(mPsi) < zero) {
487 mPsi = 0.;
488 nonZero--;
489 }
490 if (std::abs(mTheta) < zero) {
491 mTheta = 0.;
492 nonZero--;
493 }
494 if (std::abs(mPhi) < zero) {
495 mPhi = 0.;
496 nonZero--;
497 }
498 return nonZero;
499}
Definition of the base alignment parameters class.
std::ostringstream debug
void setParams(double x, double y, double z, double psi, double theta, double phi)
================ methods for direct setting of delta params
bool createLocalMatrix(TGeoHMatrix &m) const
extract local delta matrix
int getAlignableID() const
return alignable entry ID
Definition AlignParam.h:70
void setGlobalParams(double x, double y, double z, double psi, double theta, double phi)
set parameters of global delta
int rectify(double zero=1e-13)
bool setLocalRotation(double psi, double theta, double phi)
set global delta rotation from the local delta rotation
void anglesToMatrix(double psi, double theta, double phi, double *rot) const
TGeoHMatrix createMatrix() const
extract global delta matrix
void setMatrixRotation(double psi, double theta, double phi, TGeoHMatrix &dest) const
void setRotation(double psi, double theta, double phi)
set global delta rotations angles in radian
double getTheta() const
Definition AlignParam.h:52
bool setLocalTranslation(double x, double y, double z)
set global delta translation from the local delta translation
const std::string & getSymName() const
return symbolic name of the volume
Definition AlignParam.h:48
double getPhi() const
iparamater's getters
Definition AlignParam.h:50
void setMatrixTranslation(double x, double y, double z, TGeoHMatrix &dest) const
bool setLocalParams(double x, double y, double z, double psi, double theta, double phi)
================ methods for setting global delta params from local delta
void setTranslation(double x, double y, double z)
set global delta displacements in cm
double getPsi() const
Definition AlignParam.h:51
bool applyToGeometry(int printLevel=-1) const
apply object to geoemetry
bool matrixToAngles(const double *rot, double &psi, double &theta, double &phi) const
GLint GLenum GLint x
Definition glcorearb.h:403
const GLfloat * m
Definition glcorearb.h:4066
GLint y
Definition glcorearb.h:270
GLsizei const GLchar *const * path
Definition glcorearb.h:3591
GLdouble GLdouble GLdouble z
Definition glcorearb.h:843
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"