GeneralBrokenLines V03-01-03
using EIGEN
GblUtilities.cpp
Go to the documentation of this file.
1/*
2 * exampleUtil.cpp
3 *
4 * Created on: 6 Nov 2018
5 * Author: kleinwrt
6 */
7
30#include "GblUtilities.h"
31
32using namespace Eigen;
33
34namespace gbl {
35
36typedef Eigen::Matrix<double, 5, 5> Matrix5d;
37
39
44double gblMultipleScatteringError(double qbyp, double xbyx0) {
45 return 0.015 * fabs(qbyp) * sqrt(xbyx0);
46}
47
49
58Matrix5d gblSimpleJacobian(double ds, double cosl, double bfac) {
59 Matrix5d jac;
60 jac.setIdentity();
61 jac(1, 0) = -bfac * ds * cosl;
62 jac(3, 0) = -0.5 * bfac * ds * ds * cosl;
63 jac(3, 1) = ds;
64 jac(4, 2) = ds;
65 return jac;
66}
67
69double unrm() {
70 static double unrm2 = 0.0;
71 static bool cached = false;
72 if (!cached) {
73 double x, y, r;
74 do {
75 x = 2.0 * static_cast<double>(rand())
76 / static_cast<double>(RAND_MAX) - 1;
77 y = 2.0 * static_cast<double>(rand())
78 / static_cast<double>(RAND_MAX) - 1;
79 r = x * x + y * y;
80 } while (r == 0.0 || r > 1.0);
81 // (x,y) in unit circle
82 double d = sqrt(-2.0 * log(r) / r);
83 double unrm1 = x * d;
84 unrm2 = y * d;
85 cached = true;
86 return unrm1;
87 } else {
88 cached = false;
89 return unrm2;
90 }
91}
92
94double unif() {
95 return static_cast<double>(rand()) / static_cast<double>(RAND_MAX);
96}
97
99
110GblHelixPrediction::GblHelixPrediction(double sArc, const Vector2d &aPred,
111 const Vector3d &tDir, const Vector3d &uDir, const Vector3d &vDir,
112 const Vector3d &nDir, const Vector3d &aPos) :
113 sarc(sArc), pred(aPred), tdir(tDir), udir(uDir), vdir(vDir), ndir(nDir), pos(
114 aPos) {
115 global2meas << uDir.transpose(), vDir.transpose(), nDir.transpose();
116}
117
119}
120
123 return sarc;
124}
125
127const Vector2d& GblHelixPrediction::getMeasPred() const {
128 return pred;
129}
130
132const Vector3d& GblHelixPrediction::getPosition() const {
133 return pos;
134}
135
137const Vector3d& GblHelixPrediction::getDirection() const {
138 return tdir;
139}
140
143 return tdir.dot(ndir);
144}
145
147/*
148 * Curvilinear system: track direction T, U = Z x T / |Z x T|, V = T x U
149 */
150Eigen::Matrix<double, 2, 3> GblHelixPrediction::getCurvilinearDirs() const {
151 const double cosTheta = tdir[2];
152 const double sinTheta = sqrt(tdir[0] * tdir[0] + tdir[1] * tdir[1]);
153 const double cosPhi = tdir[0] / sinTheta;
154 const double sinPhi = tdir[1] / sinTheta;
155 Eigen::Matrix<double, 2, 3> uvDir;
156 uvDir << -sinPhi, cosPhi, 0., -cosPhi * cosTheta, -sinPhi * cosTheta, sinTheta;
157 return uvDir;
158}
159
161
170GblSimpleHelix::GblSimpleHelix(double aRinv, double aPhi0, double aDca,
171 double aDzds, double aZ0) :
172 rinv(aRinv), phi0(aPhi0), dca(aDca), dzds(aDzds), z0(aZ0), cosPhi0(
173 cos(phi0)), sinPhi0(sin(phi0)), xRelCenter(
174 -(1. - dca * rinv) * sinPhi0), yRelCenter(
175 (1. - dca * rinv) * cosPhi0) {
176}
177
179}
180
182
187double GblSimpleHelix::getPhi(double aRadius) const {
188 double arg = (0.5 * rinv * (aRadius * aRadius + dca * dca) - dca)
189 / (aRadius * (1.0 - rinv * dca));
190 return asin(arg) + phi0;
191}
192
194
199double GblSimpleHelix::getArcLengthR(double aRadius) const {
200 double arg = (0.5 * rinv * (aRadius * aRadius + dca * dca) - dca)
201 / (aRadius * (1.0 - rinv * dca));
202 if (fabs(arg) >= 1.) {
203 std::cout << " bad arc " << aRadius << " " << rinv << " " << dca
204 << std::endl;
205 return 0.;
206 }
207 // line
208 if (rinv == 0)
209 return sqrt(aRadius * aRadius - dca * dca);
210 // helix
211 double sxy = asin(aRadius * rinv * sqrt(1.0 - arg * arg)) / rinv;
212 if (0.5 * rinv * rinv * (aRadius * aRadius - dca * dca) - 1. + rinv * dca
213 > 0.)
214 sxy = M_PI / fabs(rinv) - sxy;
215 return sxy;
216}
217
219
223double GblSimpleHelix::getArcLengthXY(double xPos, double yPos) const {
224// line
225 if (rinv == 0)
226 return cosPhi0 * xPos + sinPhi0 * yPos;
227// helix
228 double dx = xPos * rinv - xRelCenter;
229 double dy = yPos * rinv - yRelCenter;
230 double dphi = atan2(dx, -dy) - phi0;
231 if (dphi > M_PI)
232 dphi -= 2.0 * M_PI;
233 else if (dphi < -M_PI)
234 dphi += 2.0 * M_PI;
235 return dphi / rinv;
236}
237
239
246void GblSimpleHelix::moveToXY(double xPos, double yPos, double &newPhi0,
247 double &newDca, double &newZ0) const {
248// start values
249 newPhi0 = phi0;
250 newDca = dca;
251 newZ0 = z0;
252// Based on V. Karimaki, NIM A305 (1991) 187-191, eqn (19)
253 const double u = 1. - rinv * dca;
254 const double dp = -xPos * sinPhi0 + yPos * cosPhi0 + dca;
255 const double dl = xPos * cosPhi0 + yPos * sinPhi0;
256 const double sa = 2. * dp - rinv * (dp * dp + dl * dl);
257 const double sb = rinv * xPos + u * sinPhi0;
258 const double sc = -rinv * yPos + u * cosPhi0;
259 const double sd = sqrt(1. - rinv * sa);
260// transformed parameters
261 double sArc;
262 if (rinv == 0.) {
263 newDca = dp;
264 sArc = dl;
265 } else {
266 newPhi0 = atan2(sb, sc);
267 newDca = sa / (1. + sd);
268 double dphi = newPhi0 - phi0;
269 if (dphi > M_PI)
270 dphi -= 2.0 * M_PI;
271 else if (dphi < -M_PI)
272 dphi += 2.0 * M_PI;
273 sArc = dphi / rinv;
274 }
275 newZ0 += sArc * dzds;
276}
277
279/*
280 * \param [in] refPos reference position on detector plane
281 * \param [in] uDir measurement direction 'u'
282 * \param [in] vDir measurement direction 'v'
283 */
285 const Eigen::Vector3d &uDir, const Eigen::Vector3d &vDir) const {
286// normal to (u,v) measurement plane
287 Vector3d nDir = uDir.cross(vDir).normalized();
288// ZS direction
289 const double cosLambda = 1. / sqrt(1. + dzds * dzds);
290 const double sinLambda = dzds * cosLambda;
291 double sArc2D;
292 Vector3d dist, pos, tDir;
293// line (or helix)
294 if (rinv == 0.) {
295 // track direction
296 tDir << cosLambda * cosPhi0, cosLambda * sinPhi0, sinLambda;
297 // distance (of point at dca to reference)
298 Vector3d pca(dca * sinPhi0, -dca * cosPhi0, z0);
299 dist = pca - refPos;
300 // arc-length
301 double sArc3D = -dist.dot(nDir) / tDir.dot(nDir);
302 sArc2D = sArc3D * cosLambda;
303 // position at prediction
304 pos = pca + sArc3D * tDir;
305 // distance (of point at sArc to reference)
306 dist = pos - refPos;
307 } else {
308 // initial guess of 2D arc-length
309 sArc2D = this->getArcLengthXY(refPos(0), refPos(1));
310 unsigned int nIter = 0;
311 while (nIter < 10) {
312 nIter += 1;
313 // track direction
314 const double dPhi = sArc2D * rinv;
315 const double cosPhi = cos(phi0 + dPhi);
316 const double sinPhi = sin(phi0 + dPhi);
317 tDir << cosLambda * cosPhi, cosLambda * sinPhi, sinLambda;
318 // position at prediction
319 pos << (xRelCenter + sinPhi) / rinv, (yRelCenter - cosPhi) / rinv, z0
320 + dzds * sArc2D;
321 // distance (of point at sArc to reference)
322 dist = pos - refPos;
323 // arc-length correction (linearizing helix at sArc)
324 const double sCorr3D = -dist.dot(nDir) / tDir.dot(nDir);
325 if (fabs(sCorr3D) > 0.00001) {
326 // iterate
327 sArc2D += sCorr3D * cosLambda;
328 } else {
329 // converged
330 break;
331 }
332 }
333 }
334// projections on measurement directions
335 Vector2d pred(dist.dot(uDir), dist.dot(vDir));
336 return GblHelixPrediction(sArc2D, pred, tDir, uDir, vDir, nDir, pos);
337}
338
340
354 const unsigned int aLayer, const int aDim, const double thickness,
355 Eigen::Vector3d &aCenter, Eigen::Vector2d &aResolution,
356 Eigen::Vector2d &aPrecision, Eigen::Matrix3d &measTrafo,
357 Eigen::Matrix3d &alignTrafo) :
358 name(aName), layer(aLayer), measDim(aDim), xbyx0(thickness), center(
359 aCenter), resolution(aResolution), precision(aPrecision), global2meas(
360 measTrafo), global2align(alignTrafo) {
361 udir = global2meas.row(0);
362 vdir = global2meas.row(1);
363 ndir = global2meas.row(2);
365}
366
368}
369
372 IOFormat CleanFmt(4, 0, ", ", "\n", "[", "]");
373 std::cout << " Layer " << name << " " << layer << " : " << measDim << "D, "
374 << xbyx0 << " X0, @ " << center.transpose().format(CleanFmt)
375 << ", res " << resolution.transpose().format(CleanFmt) << ", udir "
376 << udir.transpose().format(CleanFmt) << ", vdir "
377 << vdir.transpose().format(CleanFmt) << std::endl;
378}
379
381/*
382 * Alignment for **single** 1D measurement outside measurement system requires constraint (for offsets in v direction).
383 * If there are multiple 1D measurements for an alignable ('layer') with different orientations the corresponding
384 * constraints must be ignored.
385 */
387 if (measDim > 1 or alignInMeasSys)
388 return;
389 // transform vdir into alignment system
390 Eigen::Vector3d unMeasured = global2align * vdir;
391 std::cout << "Constraint 0. ! fix unmeasured direction in " << name
392 << std::endl;
393 for (int p = 0; p < 3; p++) {
394 // 'zero' suppression
395 if (fabs(unMeasured(p)) > 1.0e-10)
396 std::cout << " " << getRigidBodyGlobalLabel(p) << " "
397 << unMeasured(p) << std::endl;
398 }
399}
400
402/*
403 * Get global label for rigid body alignment parameters
404 * (3 offsets, 3 rotations) in (local) alignment system.
405 *
406 * \param[in] aPar parameter index (0..5)
407 */
409 const unsigned int aPar) const {
410 return layer * 10 + aPar + 1;
411}
412
414unsigned int GblDetectorLayer::getLayerID() const {
415 return layer;
416}
417
420 return xbyx0;
421}
422
424Eigen::Vector2d GblDetectorLayer::getResolution() const {
425 return resolution;
426}
427
429Eigen::Vector2d GblDetectorLayer::getPrecision() const {
430 return precision;
431}
432
434Eigen::Vector3d GblDetectorLayer::getCenter() const {
435 return center;
436}
437
439
442Eigen::Matrix3d GblDetectorLayer::getMeasSystemDirs() const {
443 return global2meas;;
444}
445
447
451 return global2align;;
452}
453
455
459 GblSimpleHelix hlx) const {
460 return hlx.getPrediction(center, udir, vdir);
461}
462
464
469 Eigen::Vector3d &position, Eigen::Vector3d &direction) const {
470// lever arms (for rotations)
471 Vector3d dist = position;
472// dr/dm (residual vs measurement, 1-tdir*ndir^t/tdir*ndir)
473 Matrix3d drdm = Matrix3d::Identity()
474 - (direction * ndir.transpose()) / (direction.transpose() * ndir);
475// dm/dg (measurement vs 6 rigid body parameters, global system)
476 Matrix<double, 3, 6> dmdg = Matrix<double, 3, 6>::Zero();
477 dmdg(0, 0) = 1.;
478 dmdg(0, 4) = -dist(2);
479 dmdg(0, 5) = dist(1);
480 dmdg(1, 1) = 1.;
481 dmdg(1, 3) = dist(2);
482 dmdg(1, 5) = -dist(0);
483 dmdg(2, 2) = 1.;
484 dmdg(2, 3) = -dist(1);
485 dmdg(2, 4) = dist(0);
486// drl/dg (local residuals vs rigid body parameters)
487 return global2meas * drdm * dmdg;
488}
489
491
504 Eigen::Vector3d &position, Eigen::Vector3d &direction) const {
505 // track direction in local system
506 Vector3d tLoc = global2align * direction;
507 // local slopes
508 const double uSlope = tLoc[0] / tLoc[2];
509 const double vSlope = tLoc[1] / tLoc[2];
510 // lever arms (for rotations)
511 Vector3d dist = global2align * (position - center);
512 const double uPos = dist[0];
513 const double vPos = dist[1];
514 // wPos = 0 (in detector plane)
515 // drl/dg (local residuals (du,dv) vs rigid body parameters)
516 Matrix<double, 2, 6> drldg;
517 drldg << 1.0, 0.0, -uSlope, vPos * uSlope, -uPos * uSlope, vPos, 0.0, 1.0, -vSlope, vPos
518 * vSlope, -uPos * vSlope, -uPos;
519 // avoid numerics in case of unit transformation (below)
520 if (alignInMeasSys)
521 return drldg;
522 // local (alignment) to measurement system
523 Matrix3d local2meas = global2meas * global2align.transpose();
524 return local2meas.block<2, 2>(0, 0) * drldg;
525}
526
528
535 Eigen::Vector3d &offset, Eigen::Matrix3d &rotation) const {
536 // transformation global to local
537 Matrix<double, 6, 6> glo2loc = Matrix<double, 6, 6>::Zero();
538 Matrix3d leverArms;
539 leverArms << 0., offset[2], -offset[1], -offset[2], 0., offset[0], offset[1], -offset[0], 0.;
540 glo2loc.block<3, 3>(0, 0) = rotation;
541 glo2loc.block<3, 3>(0, 3) = -rotation * leverArms;
542 glo2loc.block<3, 3>(3, 3) = rotation;
543 return glo2loc;
544}
545
547
554 Eigen::Vector3d &offset, Eigen::Matrix3d &rotation) const {
555 // transformation local to global
556 Matrix<double, 6, 6> loc2glo = Matrix<double, 6, 6>::Zero();
557 Matrix3d leverArms;
558 leverArms << 0., offset[2], -offset[1], -offset[2], 0., offset[0], offset[1], -offset[0], 0.;
559 loc2glo.block<3, 3>(0, 0) = rotation.transpose();
560 loc2glo.block<3, 3>(0, 3) = leverArms * rotation.transpose();
561 loc2glo.block<3, 3>(3, 3) = rotation.transpose();
562 return loc2glo;
563}
564
565}
Definitions for GBL utilities.
double xbyx0
normalized material thickness
Definition: GblUtilities.h:138
Eigen::Vector3d getCenter() const
Get center.
unsigned int getRigidBodyGlobalLabel(const unsigned int aPar) const
Get global label.
GblHelixPrediction intersectWithHelix(GblSimpleHelix hlx) const
Intersect with helix.
Eigen::Vector3d ndir
normal to measurement plane
Definition: GblUtilities.h:144
Eigen::Vector3d center
center
Definition: GblUtilities.h:139
double getRadiationLength() const
Get radiation length.
void print() const
Print GblDetectorLayer.
unsigned int measDim
measurement dimension (1 or 2)
Definition: GblUtilities.h:137
Eigen::Matrix< double, 2, 6 > getRigidBodyDerLocal(Eigen::Vector3d &position, Eigen::Vector3d &direction) const
Get rigid body derivatives in local (alignment) frame (rotated in measurement plane).
unsigned int getLayerID() const
Get layer ID.
Eigen::Matrix3d getMeasSystemDirs() const
Get directions of measurement system.
Eigen::Matrix< double, 6, 6 > getTrafoGlobalToLocal(Eigen::Vector3d &offset, Eigen::Matrix3d &rotation) const
Get transformation for rigid body derivatives from global to local (alignment) system.
Eigen::Matrix< double, 3, 6 > getRigidBodyDerGlobal(Eigen::Vector3d &position, Eigen::Vector3d &direction) const
Get rigid body derivatives in global frame.
Eigen::Matrix3d global2meas
transformation into measurement system
Definition: GblUtilities.h:145
unsigned int layer
layer ID
Definition: GblUtilities.h:136
GblDetectorLayer(const std::string aName, const unsigned int aLayer, const int aDim, const double thickness, Eigen::Vector3d &aCenter, Eigen::Vector2d &aResolution, Eigen::Vector2d &aPrecision, Eigen::Matrix3d &measTrafo, Eigen::Matrix3d &alignTrafo)
Create a detector layer.
Eigen::Matrix3d getAlignSystemDirs() const
Get directions of alignment system.
Eigen::Vector2d precision
measurements precision
Definition: GblUtilities.h:141
Eigen::Vector3d vdir
Definition: GblUtilities.h:143
Eigen::Vector2d getResolution() const
Get resolution.
void printMP2Constraint() const
Print MP2 constraint.
bool alignInMeasSys
alignment == measurement system?
Definition: GblUtilities.h:147
Eigen::Vector3d udir
Definition: GblUtilities.h:142
Eigen::Matrix< double, 6, 6 > getTrafoLocalToGlobal(Eigen::Vector3d &offset, Eigen::Matrix3d &rotation) const
Get transformation for rigid body derivatives from local (alignment) to global system.
Eigen::Vector2d resolution
measurements resolution
Definition: GblUtilities.h:140
std::string name
name
Definition: GblUtilities.h:135
Eigen::Vector2d getPrecision() const
Get precision.
Eigen::Matrix3d global2align
transformation into (local) alignment system
Definition: GblUtilities.h:146
Prediction on helix.
Definition: GblUtilities.h:49
Eigen::Matrix< double, 2, 3 > getCurvilinearDirs() const
Get curvilinear directions (U,V)
const Eigen::Vector3d pos
position at prediction
Definition: GblUtilities.h:70
double getArcLength() const
Get arc-length.
const Eigen::Vector2d & getMeasPred() const
Get (measurement) prediction.
const double sarc
arc-length at prediction
Definition: GblUtilities.h:64
double getCosIncidence() const
Get cosine of incidence.
Eigen::Matrix3d global2meas
transformation into measurement system
Definition: GblUtilities.h:71
const Eigen::Vector3d & getPosition() const
Get position.
const Eigen::Vector2d pred
prediction for measurement (u,v)
Definition: GblUtilities.h:65
const Eigen::Vector3d tdir
track direction at prediction
Definition: GblUtilities.h:66
GblHelixPrediction(double sArc, const Eigen::Vector2d &aPred, const Eigen::Vector3d &tDir, const Eigen::Vector3d &uDir, const Eigen::Vector3d &vDir, const Eigen::Vector3d &nDir, const Eigen::Vector3d &aPos)
Create helix prediction.
const Eigen::Vector3d & getDirection() const
Get position.
const Eigen::Vector3d ndir
normal to measurement plane
Definition: GblUtilities.h:69
Simple helix.
Definition: GblUtilities.h:78
double getArcLengthR(double aRadius) const
Get (2D) arc length for given radius (to ref. point)
void moveToXY(double xPos, double yPos, double &newPhi0, double &newDca, double &newZ0) const
Move to new reference point (X,Y)
GblHelixPrediction getPrediction(const Eigen::Vector3d &refPos, const Eigen::Vector3d &uDir, const Eigen::Vector3d &vDir) const
Get prediction.
GblSimpleHelix(double aRinv, double aPhi0, double aDca, double aDzds, double aZ0)
Create simple helix.
const double rinv
curvature (1/Radius)
Definition: GblUtilities.h:92
double getPhi(double aRadius) const
Get phi (of point on circle) for given radius (to ref. point)
const double sinPhi0
sin(phi0)
Definition: GblUtilities.h:98
double getArcLengthXY(double xPos, double yPos) const
Get (2D) arc length for given point.
const double dca
distance to origin in XY plane at PCA
Definition: GblUtilities.h:94
const double z0
offset in ZS plane
Definition: GblUtilities.h:96
const double cosPhi0
cos(phi0)
Definition: GblUtilities.h:97
const double xRelCenter
X position of circle center / R.
Definition: GblUtilities.h:99
const double dzds
slope in ZS plane (dZ/dS)
Definition: GblUtilities.h:95
const double phi0
azimuth at PCA (point of closest approach to origin in XY plane, defines arc-length S=0)
Definition: GblUtilities.h:93
const double yRelCenter
Y position of circle center / R.
Definition: GblUtilities.h:100
Namespace for the general broken lines package.
double unrm()
unit normal distribution, Box-Muller method, polar form
double gblMultipleScatteringError(double qbyp, double xbyx0)
Multiple scattering error.
double unif()
uniform distribution [0..1]
Matrix5d gblSimpleJacobian(double ds, double cosl, double bfac)
Simple jacobian.
Eigen::Matrix< double, 5, 5 > Matrix5d
Definition: GblData.h:46