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 <fairlogger/Logger.h>
16#include <TGeoManager.h>
17#include <TGeoMatrix.h>
18#include <TGeoOverlap.h>
19#include <TGeoPhysicalNode.h>
20
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 : mSymName(symname), mAlignableID(algID)
31{
37
38 if (global) {
39 setGlobalParams(x, y, z, psi, theta, phi);
40 } else {
41 setLocalParams(x, y, z, psi, theta, phi);
42 }
43}
44
45//___________________________________________________
46AlignParam::AlignParam(const char* symname, int algID, TGeoMatrix& m, bool global)
47 : mSymName(symname), 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 && !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 if (!gGeoManager || !gGeoManager->IsClosed()) {
227 LOG(error) << "Can't get the local alignment object parameters! gGeoManager doesn't exist or it is still open!";
228 return false;
229 }
230
231 const char* symname = getSymName().c_str();
232 TGeoPhysicalNode* node;
233 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
234 if (pne) {
235 if (!pne->GetPhysicalNode()) {
236 node = gGeoManager->MakeAlignablePN(pne);
237 } else {
238 node = pne->GetPhysicalNode();
239 }
240 } else {
241 LOG(warning) << "The symbolic volume name " << symname
242 << " does not correspond to a physical entry. Using it as volume path!";
243 node = (TGeoPhysicalNode*)gGeoManager->MakePhysicalNode(symname);
244 }
245
246 if (!node) {
247 LOG(error) << "Volume name or path " << symname << " is not valid!";
248 return false;
249 }
250 m = createMatrix();
251 TGeoHMatrix gprime, gprimeinv;
252 gprime = *node->GetMatrix();
253 gprimeinv = gprime.Inverse();
254 m.Multiply(&gprime);
255 m.MultiplyLeft(&gprimeinv);
256
257 return true;
258}
259
260//_____________________________________________________________________________
262{
266 //
267 if (!gGeoManager || !gGeoManager->IsClosed()) {
268 LOG(error) << "Can't apply the alignment object! gGeoManager doesn't exist or it is still open!";
269 return false;
270 }
271
272 if (gGeoManager->IsLocked()) {
273 LOG(error) << "Can't apply the alignment object! Geometry is locked!";
274 return false;
275 }
276
277 const char* symname = getSymName().c_str();
278 const char* path;
279 TGeoPhysicalNode* node;
280 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
281 if (pne) {
282 path = pne->GetTitle();
283 node = gGeoManager->MakeAlignablePN(pne);
284 } else {
285 LOG(debug) << "The symbolic volume name " << symname
286 << " does not correspond to a physical entry. Using it as a volume path!";
287 path = symname;
288 if (!gGeoManager->CheckPath(path)) {
289 LOG(error) << "Volume path " << path << " is not valid";
290 return false;
291 }
292 if (gGeoManager->GetListOfPhysicalNodes()->FindObject(path)) {
293 LOG(error) << "Volume path " << path << " has been misaligned already!";
294 return false;
295 }
296 node = (TGeoPhysicalNode*)gGeoManager->MakePhysicalNode(path);
297 }
298
299 if (!node) {
300 LOG(error) << "Volume path " << path << " is not valid";
301 return false;
302 }
303
304 // double threshold = 0.001;
305
306 TGeoHMatrix gprime = *node->GetMatrix();
307 TGeoHMatrix align = createMatrix();
308 gprime.MultiplyLeft(&align);
309 TGeoHMatrix* ginv = new TGeoHMatrix; // TGeoPhysicalNode takes and manages raw pointer, need naked new!
310 TGeoHMatrix* g = node->GetMatrix(node->GetLevel() - 1);
311 *ginv = g->Inverse();
312 *ginv *= gprime;
313
314 LOG(debug) << "Aligning volume " << symname;
315
316 node->Align(ginv);
317
318 return true;
319}
320
321//_____________________________________________________________________________
323{
327 //
328 if (!gGeoManager) {
329 LOG(error) << "gGeoManager doesn't exist or it is still open: unable to return meaningful level value.";
330 return -1;
331 }
332 const char* symname = getSymName().c_str();
333 const char* path;
334 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
335 if (pne) {
336 path = pne->GetTitle();
337 } else {
338 path = symname;
339 }
340
341 TString pathStr = path;
342 int lev = pathStr.CountChar('/');
343 return (pathStr[0] != '/') ? ++lev : lev;
344}
345
346//_____________________________________________________________________________
348{
349 // print parameters
350 printf("%s : %6d | X: %+e Y: %+e Z: %+e | pitch: %+e roll: %+e yaw: %e\n", getSymName().c_str(), getAlignableID(), getX(),
351 getY(), getZ(), getPsi(), getTheta(), getPhi());
352}
353
354//_____________________________________________________________________________
355void AlignParam::setGlobalParams(double x, double y, double z, double psi, double theta, double phi)
356{
358 setTranslation(x, y, z);
359 setRotation(psi, theta, phi);
360}
361
362//_____________________________________________________________________________
363void AlignParam::setRotation(double psi, double theta, double phi)
364{
366 mPsi = psi;
367 mTheta = theta;
368 mPhi = phi;
369}
370
371//_____________________________________________________________________________
372void AlignParam::setTranslation(double x, double y, double z)
373{
375 mX = x;
376 mY = y;
377 mZ = z;
378}
379
380//_____________________________________________________________________________
381void AlignParam::setGlobalParams(const TGeoMatrix& m)
382{
385 setRotation(m);
386}
387
388//___________________________________________________
389void AlignParam::setMatrixTranslation(double x, double y, double z, TGeoHMatrix& dest) const
390{
392 double tra[3] = {x, y, z};
393 dest.SetTranslation(tra);
394}
395
396//_____________________________________________________________________________
397bool AlignParam::setLocalTranslation(double x, double y, double z)
398{
404
405 TGeoHMatrix m;
406 double tr[3] = {x, y, z};
407 m.SetTranslation(tr);
408
409 return setLocalParams(m);
410}
411
412//_____________________________________________________________________________
413bool AlignParam::setLocalTranslation(const TGeoMatrix& m)
414{
419
420 TGeoHMatrix mtr;
421 mtr.SetTranslation(m.GetTranslation());
422 return setLocalParams(mtr);
423}
424
425//_____________________________________________________________________________
426bool AlignParam::setLocalRotation(double psi, double theta, double phi)
427{
433
434 TGeoHMatrix m;
435 setMatrixRotation(psi, theta, phi, m);
436 return setLocalParams(m);
437}
438
439//_____________________________________________________________________________
440bool AlignParam::setLocalRotation(const TGeoMatrix& m)
441{
446
447 TGeoHMatrix rotm;
448 rotm.SetRotation(m.GetRotationMatrix());
449 return setLocalParams(rotm);
450}
451
452//_____________________________________________________________________________
453int AlignParam::rectify(double zero)
454{
455 int nonZero = 6;
456 if (std::abs(mX) < zero) {
457 mX = 0.;
458 }
459 if (std::abs(mY) < zero) {
460 mY = 0.;
461 nonZero--;
462 }
463 if (std::abs(mZ) < zero) {
464 mZ = 0.;
465 nonZero--;
466 }
467 if (std::abs(mPsi) < zero) {
468 mPsi = 0.;
469 nonZero--;
470 }
471 if (std::abs(mTheta) < zero) {
472 mTheta = 0.;
473 nonZero--;
474 }
475 if (std::abs(mPhi) < zero) {
476 mPhi = 0.;
477 nonZero--;
478 }
479 return nonZero;
480}
Definition of the base alignment parameters class.
std::ostringstream debug
bool createLocalMatrix(TGeoHMatrix &m) const
extract local delta matrix
int getAlignableID() const
return alignable entry ID
Definition AlignParam.h:67
void setGlobalParams(double x, double y, double z, double psi, double theta, double phi)
================ methods for direct setting of delta params
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:49
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:45
double getPhi() const
iparamater's getters
Definition AlignParam.h:47
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:48
bool applyToGeometry() 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
GLboolean GLboolean g
Definition glcorearb.h:1233
GLsizei const GLchar *const * path
Definition glcorearb.h:3591
GLdouble GLdouble GLdouble z
Definition glcorearb.h:843
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"