Project
Loading...
Searching...
No Matches
GeometricalConstraint.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
16
18#include "Align/AlignConfig.h"
20#include "Align/utils.h"
21#include "Framework/Logger.h"
22#include <TGeoMatrix.h>
23#include <TMath.h>
24#include <cstdio>
25
27
28using namespace o2::align::utils;
29using namespace TMath;
30
31namespace o2
32{
33namespace align
34{
35
36//______________________________________________________
38{
39 // write for PEDE eventual constraints on children movement in parent frame
40 //
41 enum { kOff,
42 kOn,
43 kOnOn };
44 enum { kConstr,
45 kMeas };
46 const char* comment[3] = {" ", "! ", "!!"};
47 const char* kKeyConstr[2] = {"constraint", "measurement"};
48 //
49 bool doJac = !getNoJacobian(); // do we need jacobian evaluation?
50 int nch = getNChildren();
51 std::unique_ptr<double[]> cstrArr(new double[nch * kNDOFGeom * kNDOFGeom]);
52 memset(cstrArr.get(), 0, nch * kNDOFGeom * kNDOFGeom * sizeof(double));
53 // we need for each children the matrix for vector transformation from children frame
54 // (in which its DOFs are defined, LOC or TRA) to this parent variation frame
55 // matRel = mPar^-1*mChild
56 TGeoHMatrix mPar;
57 //
58 const auto& algConf = AlignConfig::Instance();
59 // in case of parent assigned use its matrix,
60 // otherwise Alice global frame is assumed to be the parent -> Unit matrix
61 if (mParent && doJac) {
62 if (mParent->isFrameTRA()) {
63 mParent->getMatrixT2G(mPar);
64 } // tracking to global
65 else {
66 mPar = mParent->getMatrixL2GIdeal();
67 } // local to global
68 mPar = mPar.Inverse();
69 }
70 //
71 auto jac = cstrArr.get();
72 int nContCh[kNDOFGeom] = {0}; // we need at least one contributing children DOF to constrain the parent DOF
73 for (int ich = 0; ich < nch; ich++) {
74 auto child = getChild(ich);
75 if (doJac) { // calculate jacobian
76 TGeoHMatrix matRel;
77 if (child->isFrameTRA()) {
78 child->getMatrixT2G(matRel);
79 } // tracking to global
80 else {
81 matRel = child->getMatrixL2GIdeal();
82 } // local to global
83 matRel.MultiplyLeft(&mPar);
84 constrCoefGeom(matRel, jac);
85 //
86 for (int ics = 0; ics < kNDOFGeom; ics++) { // DOF of parent to be constrained
87 for (int ip = 0; ip < kNDOFGeom; ip++) { // count contributing DOFs
88 double jv = jac[ics * kNDOFGeom + ip];
89 if (!isZeroAbs(jv) && child->isFreeDOF(ip) && child->getParErr(ip) >= 0) {
90 nContCh[ip]++;
91 }
92 }
93 }
94 } else { // simple constraint on the sum of requested DOF
95 for (int ip = 0; ip < kNDOFGeom; ip++) {
96 if (child->isFreeDOF(ip) && child->getParErr(ip) >= 0) {
97 nContCh[ip]++;
98 }
99 jac[ip * kNDOFGeom + ip] = 1.;
100 }
101 }
102 jac += kNDOFGeom * kNDOFGeom; // matrix for next slot
103 }
104 for (int ics = 0; ics < kNDOFGeom; ics++) {
105 if (!isDOFConstrained(ics)) {
106 continue;
107 }
108 int cmtStatus = nContCh[ics] > 0 ? kOff : kOn; // do we comment this constraint?
109 if (cmtStatus) {
110 if (algConf.verbose > 0) {
111 LOG(info) << "No contributors to constraint of " << getDOFName(ics) << " of " << getName();
112 }
113 }
114 if (mSigma[ics] > 0) {
115 fprintf(conOut, "\n%s%s\t%e\t%e\t%s %s of %s Auto\n", comment[cmtStatus], kKeyConstr[kMeas], 0.0, mSigma[ics],
116 comment[kOnOn], getDOFName(ics), getName().c_str());
117 } else {
118 fprintf(conOut, "\n%s%s\t%e\t%s %s of %s Auto\n", comment[cmtStatus], kKeyConstr[kConstr], 0.0,
119 comment[kOnOn], getDOFName(ics), getName().c_str());
120 }
121 for (int ich = 0; ich < nch; ich++) { // contribution from this children DOFs to constraint
122 auto child = getChild(ich);
123 jac = cstrArr.get() + kNDOFGeom * kNDOFGeom * ich;
124 if (cmtStatus) {
125 fprintf(conOut, "%s", comment[cmtStatus]);
126 } // comment out contribution
127 // first write real constraints
128 for (int ip = 0; ip < kNDOFGeom; ip++) {
129 double jv = jac[ics * kNDOFGeom + ip];
130 if (child->isFreeDOF(ip) && !isZeroAbs(jv) && child->getParErr(ip) >= 0) {
131 fprintf(conOut, "%9d %+.3e\t", child->getParLab(ip), jv);
132 }
133 } // loop over DOF's of children contributing to this constraint
134 // now, after comment, write disabled constraints
135 fprintf(conOut, "%s ", comment[kOn]);
136 if (doJac) {
137 for (int ip = 0; ip < kNDOFGeom; ip++) {
138 double jv = jac[ics * kNDOFGeom + ip];
139 if (child->isFreeDOF(ip) && !isZeroAbs(jv) && child->getParErr(ip) >= 0) {
140 continue;
141 }
142 fprintf(conOut, "%9d %+.3e\t", child->getParLab(ip), jv);
143 } // loop over DOF's of children contributing to this constraint
144 }
145 fprintf(conOut, "%s from %s\n", comment[kOnOn], child->getSymName());
146 } // loop over children
147 } // loop over constraints in parent volume
148}
149
150//______________________________________________________
152{
153 // check how the constraints are satysfied
154 int nch = getNChildren();
155 if (!nch) {
156 return;
157 }
158 //
159 bool doJac = !getNoJacobian(); // do we need jacobian evaluation?
160 std::unique_ptr<double[]> cstrArr(new double[nch * kNDOFGeom * kNDOFGeom]);
161 memset(cstrArr.get(), 0, nch * kNDOFGeom * kNDOFGeom * sizeof(double));
162 // we need for each children the matrix for vector transformation from children frame
163 // (in which its DOFs are defined, LOC or TRA) to this parent variation frame
164 // matRel = mPar^-1*mChild
165 TGeoHMatrix mPar;
166 // in case of parent assigned use its matrix,
167 // otherwise Alice global frame is assumed to be the parent -> Unit matrix
168 if (mParent && doJac) {
169 if (mParent->isFrameTRA()) {
170 mParent->getMatrixT2G(mPar);
171 } // tracking to global
172 else {
173 mPar = mParent->getMatrixL2GIdeal();
174 } // local to global
175 mPar = mPar.Inverse();
176 }
177 //
178 auto jac = cstrArr.get();
179 double parsTotEx[kNDOFGeom] = {0}; // explicitly calculated total modification
180 double parsTotAn[kNDOFGeom] = {0}; // analyticaly calculated total modification
181 //
182 printf("\n\n ----- Constraints Validation for %s Auto ------\n", getName().c_str());
183 printf(" chld| ");
184 for (int jp = 0; jp < kNDOFGeom; jp++) {
185 printf(" %3s:%3s An/Ex |", getDOFName(jp), isDOFConstrained(jp) ? "ON " : "OFF");
186 }
187 printf(" | ");
188 for (int jp = 0; jp < kNDOFGeom; jp++) {
189 printf(" D%3s ", getDOFName(jp));
190 }
191 printf(" ! %s\n", getName().c_str());
192 for (int ich = 0; ich < nch; ich++) {
193 auto child = getChild(ich);
194 double parsC[kNDOFGeom] = {0}, parsPAn[kNDOFGeom] = {0}, parsPEx[kNDOFGeom] = {0};
195 for (int jc = kNDOFGeom; jc--;) {
196 parsC[jc] = child->getParVal(jc);
197 } // child params in child frame
198 printf("#%3d | ", ich);
199 //
200 if (doJac) {
201 TGeoHMatrix matRel;
202 if (child->isFrameTRA()) {
203 child->getMatrixT2G(matRel);
204 } // tracking to global
205 else {
206 matRel = child->getMatrixL2GIdeal();
207 } // local to global
208 //
209 matRel.MultiplyLeft(&mPar);
210 constrCoefGeom(matRel, jac); // Jacobian for analytical constraint used by MillePede
211 //
212 TGeoHMatrix tau;
213 child->delta2Matrix(tau, parsC); // child correction matrix in the child frame
214 const TGeoHMatrix& matreli = matRel.Inverse();
215 tau.Multiply(&matreli);
216 tau.MultiplyLeft(&matRel); // child correction matrix in the parent frame
218 // tmpPar.SetMatrix(tau);
219 // SetMatrix does setTranslation and setRotation afterwars;
220 tmpPar.setTranslation(tau);
221 tmpPar.setRotation(tau);
222 //tmpPar.GetTranslation(&parsPEx[0]);
223 // get Translation gets x,y,z;
224 parsPEx[0] = tmpPar.getX();
225 parsPEx[1] = tmpPar.getY();
226 parsPEx[2] = tmpPar.getZ();
227 //tmpPar.GetAngles(&parsPEx[3]); // explicitly calculated child params in parent frame
228 // gets angles
229 parsPEx[3] = tmpPar.getPsi();
230 parsPEx[4] = tmpPar.getTheta();
231 parsPEx[5] = tmpPar.getPhi();
232 //
233 // analytically calculated child params in parent frame
234 for (int jp = 0; jp < kNDOFGeom; jp++) {
235 for (int jc = 0; jc < kNDOFGeom; jc++) {
236 parsPAn[jp] += jac[jp * kNDOFGeom + jc] * parsC[jc];
237 }
238 parsTotAn[jp] += parsPAn[jp]; // analyticaly calculated total modification
239 parsTotEx[jp] += parsPEx[jp]; // explicitly calculated total modification
240 //
241 printf("%+.1e/%+.1e ", parsPAn[jp], parsPEx[jp]);
242 //
243 }
244 //
245 jac += kNDOFGeom * kNDOFGeom; // matrix for next slot
246 } else {
247 for (int jc = 0; jc < kNDOFGeom; jc++) {
248 bool acc = child->isFreeDOF(jc) && child->getParErr(jc) >= 0;
249 if (acc) {
250 printf(" %+.3e ", parsC[jc]);
251 parsTotAn[jc] += parsC[jc];
252 } else {
253 printf(" /* %+.3e */ ", parsC[jc]);
254 } // just for info, not in the constraint
255 }
256 }
257 printf(" | ");
258 for (int jc = 0; jc < kNDOFGeom; jc++) {
259 printf("%+.1e ", parsC[jc]);
260 } // child proper corrections
261 printf(" ! %s\n", child->getSymName());
262 }
263 //
264 printf(" Tot | ");
265 for (int jp = 0; jp < kNDOFGeom; jp++) {
266 if (doJac) {
267 printf("%+.1e/%+.1e ", parsTotAn[jp], parsTotEx[jp]);
268 } else {
269 if (isDOFConstrained(jp)) {
270 printf(" %+.3e ", parsTotAn[jp]);
271 } else {
272 printf(" /* %+.3e */ ", parsTotAn[jp]);
273 }
274 }
275 }
276 printf(" | ");
277 if (mParent) {
278 for (int jp = 0; jp < kNDOFGeom; jp++) {
279 printf("%+.1e ", mParent->getParVal(jp));
280 }
281 } // parent proper corrections
282 else {
283 printf(" no parent -> %s ", doJac ? "Global" : "Simple");
284 }
285 printf(" ! <----- %s\n", getName().c_str());
286 //
287 printf(" Sig | ");
288 for (int jp = 0; jp < kNDOFGeom; jp++) {
289 if (isDOFConstrained(jp)) {
290 printf(" %+.3e ", mSigma[jp]);
291 } else {
292 printf(" /* %+.3e */ ", mSigma[jp]);
293 }
294 }
295 printf(" ! <----- \n");
296}
297
298//_________________________________________________________________
299void GeometricalConstraint::constrCoefGeom(const TGeoHMatrix& matRD, double* jac /*[kNDOFGeom][kNDOFGeom]*/) const
300{
301 // If the transformation R brings the vector from "local" frame to "master" frame as V=R*v
302 // then application of the small LOCAL correction tau to vector v is equivalent to
303 // aplication of correction TAU in MASTER framce V' = R*tau*v = TAU*R*v
304 // with TAU = R*tau*R^-1
305 // Constraining the LOCAL modifications of child volumes to have 0 total movement in their parent
306 // frame is equivalent to request that sum of all TAU matrices is unity matrix, or TAU-I = 0.
307 //
308 // This routine calculates derivatives of the TAU-I matrix over local corrections x,y,z, psi,tht,phi
309 // defining matrix TAU. In small corrections approximation the constraint is equivalent to
310 // Sum_over_child_volumes{ [dTAU/dParam]_ij * deltaParam } = 0
311 // for all elements ij of derivative matrices. Since only 6 out of 16 matrix params are independent,
312 // we request the constraint only for [30](X), [31](Y), [32](Z), [12](psi), [02](tht), [01](phi)
313 // Choice defined by convention of AliAlgObg::Angles2Matrix (need elements ~ linear in corrections)
314 //
315 TGeoHMatrix matRI = matRD.Inverse();
316 const int ij[kNDOFGeom][2] = {{3, 0}, {3, 1}, {3, 2}, {1, 2}, {0, 2}, {0, 1}};
317 //
318 const double *rd = matRD.GetRotationMatrix(), *ri = matRI.GetRotationMatrix();
319 const double * ti = matRI.GetTranslation();
320 //
322 // const double cf[kNDOFGeom] = {1., 1., 1., DegToRad(), DegToRad(), DegToRad()};
323 // const double sgc[kNDOFGeom] = {1., 1., 1., -RadToDeg(), RadToDeg(), -RadToDeg()};
324
325 // the angles are in radians
326 const double cf[kNDOFGeom] = {1., 1., 1., 1., 1., 1.};
327 const double sgc[kNDOFGeom] = {1., 1., 1., -1., 1., -1.};
328
329 //
330 // since the TAU is supposed to convert local corrections in the child frame to corrections
331 // in the parent frame, we scale angular degrees of freedom back to degrees and assign the
332 // sign of S in the S*sin(angle) in the matrix, so that the final correction has a correct
333 // sign, due to the choice of euler angles in the AliAlignObj::AnglesToMatrix
334 // costhe*cosphi; -costhe*sinphi; sinthe;
335 // sinpsi*sinthe*cosphi + cospsi*sinphi; -sinpsi*sinthe*sinphi + cospsi*cosphi; -costhe*sinpsi;
336 // -cospsi*sinthe*cosphi + sinpsi*sinphi; cospsi*sinthe*sinphi + sinpsi*cosphi; costhe*cospsi;
337 //
338 const double kJTol = 1e-4; // treat derivatives below this threshold as 0
339 //
340 double dDPar[kNDOFGeom][4][4] = {
341 // dDX[4][4]
342 {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {rd[0], rd[3], rd[6], 0}},
343 // dDY[4][4]
344 {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {rd[1], rd[4], rd[7], 0}},
345 // dDZ[4][4]
346 {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {rd[2], rd[5], rd[8], 0}},
347 // dDPSI[4][4]
348 {{rd[2] * ri[3] - rd[1] * ri[6], rd[2] * ri[4] - rd[1] * ri[7], rd[2] * ri[5] - rd[1] * ri[8], 0},
349 {rd[5] * ri[3] - rd[4] * ri[6], rd[5] * ri[4] - rd[4] * ri[7], rd[5] * ri[5] - rd[4] * ri[8], 0},
350 {rd[8] * ri[3] - rd[7] * ri[6], rd[8] * ri[4] - rd[7] * ri[7], rd[8] * ri[5] - rd[7] * ri[8], 0},
351 {rd[2] * ti[1] - rd[1] * ti[2], rd[5] * ti[1] - rd[4] * ti[2], rd[8] * ti[1] - rd[7] * ti[2], 0}},
352 // dDTHT[4][4]
353 {{rd[0] * ri[6] - rd[2] * ri[0], rd[0] * ri[7] - rd[2] * ri[1], rd[0] * ri[8] - rd[2] * ri[2], 0},
354 {rd[3] * ri[6] - rd[5] * ri[0], rd[3] * ri[7] - rd[5] * ri[1], rd[3] * ri[8] - rd[5] * ri[2], 0},
355 {rd[6] * ri[6] - rd[8] * ri[0], rd[6] * ri[7] - rd[8] * ri[1], rd[6] * ri[8] - rd[8] * ri[2], 0},
356 {rd[0] * ti[2] - rd[2] * ti[0], rd[3] * ti[2] - rd[5] * ti[0], rd[6] * ti[2] - rd[8] * ti[0], 0}},
357 // dDPHI[4][4]
358 {{rd[1] * ri[0] - rd[0] * ri[3], rd[1] * ri[1] - rd[0] * ri[4], rd[1] * ri[2] - rd[0] * ri[5], 0},
359 {rd[4] * ri[0] - rd[3] * ri[3], rd[4] * ri[1] - rd[3] * ri[4], rd[4] * ri[2] - rd[3] * ri[5], 0},
360 {rd[7] * ri[0] - rd[6] * ri[3], rd[7] * ri[1] - rd[6] * ri[4], rd[7] * ri[2] - rd[6] * ri[5], 0},
361 {rd[1] * ti[0] - rd[0] * ti[1], rd[4] * ti[0] - rd[3] * ti[1], rd[7] * ti[0] - rd[6] * ti[1], 0}},
362 };
363 //
364 for (int cs = 0; cs < kNDOFGeom; cs++) {
365 int i = ij[cs][0], j = ij[cs][1];
366 for (int ip = 0; ip < kNDOFGeom; ip++) {
367 double jval = sgc[cs] * dDPar[ip][i][j] * cf[ip];
368 jac[cs * kNDOFGeom + ip] = (Abs(jval) > kJTol) ? jval : 0; // [cs][ip]
369 }
370 }
371}
372
373//______________________________________________________
375{
376 // print info
377 printf("Constraint on ");
378 for (int i = 0; i < kNDOFGeom; i++) {
379 if (isDOFConstrained(i)) {
380 printf("%3s (Sig:%+e) ", getDOFName(i), getSigma(i));
381 }
382 }
383 printf(" | %s Auto\n", getName().c_str());
384 if (getNoJacobian()) {
385 printf("!!! This is explicit constraint on sum of DOFs (no Jacobian)!!!\n");
386 }
387 for (int i = 0; i < getNChildren(); i++) {
388 auto child = getChild(i);
389 printf("%3d %s\n", i, child->getSymName());
390 }
391}
392
393} // namespace align
394} // namespace o2
Definition of the base alignment parameters class.
Configuration file for global alignment.
Collection of auxillary methods.
int32_t i
ClassImp(o2::align::GeometricalConstraint)
Descriptor of geometrical constraint.
uint32_t j
Definition RawData.h:0
void getMatrixT2G(TGeoHMatrix &m) const
const TGeoHMatrix & getMatrixL2GIdeal() const
float getParVal(int par) const
Definition DOFSet.h:39
void writeChildrenConstraints(FILE *conOut) const
const AlignableVolume * getChild(int i) const
const char * getDOFName(int i) const
void constrCoefGeom(const TGeoHMatrix &matRD, double *jac) const
void setRotation(double psi, double theta, double phi)
set global delta rotations angles in radian
double getTheta() const
Definition AlignParam.h:49
double getPhi() const
iparamater's getters
Definition AlignParam.h:47
void setTranslation(double x, double y, double z)
set global delta displacements in cm
double getPsi() const
Definition AlignParam.h:48
constexpr bool isZeroAbs(double d) noexcept
Definition utils.h:63
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::random_device rd