ATLAS Offline Software
Loading...
Searching...
No Matches
VP1ErrorUtils.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
3*/
4
5
7// //
8// Header file for class VP1ErrorUtils //
9// //
10// Description: Utilities for drawing errors for various //
11// measurements //
12// //
13// Author: Troels Kofoed Jacobsen //
14// Initial version: July 2008 //
15// //
16// Update: Riccardo Maria BIANCHI Feb 2014 //
17// //
19
21#include "VP1Base/VP1Msg.h"
27
28#include <Inventor/nodes/SoSeparator.h>
29#include <Inventor/nodes/SoTranslation.h>
30#include <Inventor/nodes/SoRotationXYZ.h>
31#include <Inventor/nodes/SoTransform.h>
32#include <Inventor/nodes/SoLineSet.h>
33#include <Inventor/nodes/SoVertexProperty.h>
34#include <Inventor/nodes/SoCylinder.h>
35#include <Inventor/nodes/SoComplexity.h>
36#include <Inventor/nodes/SoDrawStyle.h>
38
39#include "TrkSurfaces/Surface.h"
41
42#include <cmath>
43
44#include <Eigen/Eigenvalues>
45
46
47typedef AmgSymMatrix(2) AmgCovMatrix;
48
49
50
51
52//____________________________________________________________________
54 const AmgSymMatrix(5)& covmat,
55 const double& sigmaScale,
56 int numNodes,
57 const double& translate,
58 const bool& symmetric)
59{
60 VP1Msg::messageVerbose("VP1ErrorUtils::addRotatedErrorEllipse()");
61
62 if (!covMatrixIsSane(covmat)) {
63 VP1Msg::message("WARNING in VP1ErrorUtils: covariance matrix isn't sane (i.e. contains NaNs)");
64 return;
65 }
66 if (sigmaScale!=sigmaScale) VP1Msg::message("WARNING in VP1ErrorUtils: sigmaScale nan");
67 if (translate!=translate) VP1Msg::message("WARNING in VP1ErrorUtils: translate nan");
68
69 // Eigenvalues of covariance matrix (symmetric)
70 Eigen::SelfAdjointEigenSolver<AmgSymMatrix(5)> eigensolver(covmat);
71 if (eigensolver.info() != Eigen::Success) {
72 VP1Msg::message("ERROR! problems with the 'eigensolver'!");
73 abort();
74 }
75 double v0 = eigensolver.eigenvalues()[0];
76 double v1 = eigensolver.eigenvalues()[1];
77
78
79 if ( (v0-v1)<0.000005 ) {
80 VP1Msg::message("WARNING in VP1ErrorUtils: v0 or v1 is zero. Not drawing RotatedErrorEllipse");
81 return;
82 }
83 if (v0!=v0) VP1Msg::message("WARNING in VP1ErrorUtils: v0 nan");
84 if (v1!=v1) VP1Msg::message("WARNING in VP1ErrorUtils: v1 nan");
85
86 // Rotation of error ellipse
87 if (covmat(0,1) != covmat(0,1)) VP1Msg::message("WARNING in VP1ErrorUtils: covmat(0,1) nan");
88
89 double theta=0.5*asin(2 * covmat(0,1) / (v0-v1));
90 if (theta!=theta) {
91 VP1Msg::message("WARNING in VP1ErrorUtils: theta NaN. Setting to zero. v0,v1="+QString::number(v0)+","+QString::number(v1));
92 theta=0.0;
93 }
94 SoNode * ellipse = VP1QtInventorUtils::createEllipse( sigmaScale * sqrt(v0) ,
95 sigmaScale * sqrt(v1) ,
96 numNodes);
97
98 SoRotationXYZ * r1 = new SoRotationXYZ;
99 r1->axis = SoRotationXYZ::Z;
100 r1->angle = theta;
101 gr->addChild( r1 );
102
103 if (translate != 0.0)
104 {
105 SoTranslation * t0 = new SoTranslation;
106 t0->translation.setValue(0.0,0.0, translate );
107 gr->addChild( t0 );
108 if (symmetric)
109 {
110 gr->addChild( ellipse );
111 SoTranslation * t1 = new SoTranslation;
112 t1->translation.setValue(0.0,0.0, -2*translate );
113 gr->addChild( t1 );
114 }
115 }
116
117 gr->addChild( ellipse );
118 return;
119}
120
122 const double& error,
123 const double& sigmaScale,
124 const double& length)
125{
126
127 VP1Msg::messageVerbose("VP1ErrorUtils::addSimple1DError()");
128 //Return a box.
129 // SoGenericBox::initClass();
130 // SoGenericBox* cube = new SoGenericBox;
131 // cube->setParametersForBox(0.5*std::fabs(error*sigmaScale),0.5*std::fabs(length),0.4);
132 // cube->drawEdgeLines = true;
133 // gr->addChild( cube );
134
135 SoVertexProperty * vertices = new SoVertexProperty;
136 int iver(0);
137 float xpos=0.5*std::fabs(error*sigmaScale);
138 float ypos=0.5*std::fabs(length);
139
140 vertices->vertex.set1Value(iver++,-xpos,-ypos,0.0);
141 vertices->vertex.set1Value(iver++,-xpos,+ypos,0.0);
142 vertices->vertex.set1Value(iver++,+xpos,-ypos,0.0);
143 vertices->vertex.set1Value(iver++,+xpos,+ypos,0.0);
144
145
146 SoLineSet * errbars = new SoLineSet;
147 errbars->vertexProperty = vertices;
148 int numlines(0);
149 errbars->numVertices.set1Value(numlines++,2);
150 errbars->numVertices.set1Value(numlines++,2);
151 gr->addChild( errbars );
152
153 iver=0;
154 SoVertexProperty * vertices2 = new SoVertexProperty;
155 vertices2->vertex.set1Value(iver++,-xpos,0.0,0.0);
156 vertices2->vertex.set1Value(iver++,+xpos,0.0,0.0);
157
158 SoLineSet * errbarConnection = new SoLineSet;
159 errbarConnection->vertexProperty = vertices2;
160 errbarConnection->numVertices.set1Value(0,2);
161
162 SoDrawStyle *drawStyle = new SoDrawStyle;
163 drawStyle->style.setValue(SoDrawStyle::LINES);
164 drawStyle->linePattern.setValue(0xFF00);
165 gr->addChild(drawStyle);
166 gr->addChild( errbarConnection );
167
168 return;
169}
170
171//____________________________________________________________________
172void VP1ErrorUtils::errorAtPlaneSurface( SoSeparator* errSimple,
173 SoSeparator* errDetailed,
174 const AmgSymMatrix(5)& tmpcovmat,
175 const Trk::Surface* theSurface,
176 const Amg::Vector3D& p1,
177 const double& sigmaScale,
178 int numNodes,
179 const bool& moveToSurface,
180 const bool& force1D,
181 const bool& addTransform)
182{
183 VP1Msg::messageVerbose("VP1ErrorUtils::errorAtPlaneSurface()");
184
185 if (!covMatrixIsSane(tmpcovmat)) {
186 VP1Msg::message("WARNING in VP1ErrorUtils: covariance matrix isn't sane (i.e. contains NaNs)");
187 std::cout<<tmpcovmat<<std::endl;
188 return;
189 }
190 // const Trk::CovarianceMatrix& tmpcovmat = meas->localErrorMatrix().covariance();
191 SoSeparator * ellipseGrp = new SoSeparator;
192
193 // Translation used to put the ellipse above the surface
194 //SoTranslation * t0 = new SoTranslation;
195 //t0->translation.setValue(0.0,0.0, SurfaceToSoNode::surfaceThickness / 2.0 + 0.001 );
196 //ellipseGrp->addChild( t0 );
197
198
199 if (force1D){
200 float length=50.0;
201 // const Trk::RectangleBounds* rBounds = dynamic_cast<const Trk::RectangleBounds*>(&(theSurface->bounds()));
202 // if (rBounds) length=rBounds->halflengthY ()*2.0;
203 // FIXME = add more bounds.
204 addSimple1DError(ellipseGrp, tmpcovmat(0,0), sigmaScale, length );
205 } else {
206 if (moveToSurface)
207 {
208 addRotatedErrorEllipse(ellipseGrp, tmpcovmat, sigmaScale,numNodes, SurfaceToSoNode::surfaceThickness / 2.0 + 0.001, true);
209 } else{
210 addRotatedErrorEllipse(ellipseGrp, tmpcovmat, sigmaScale,numNodes, 0.0, false);
211 }
212 }
213
214 if(addTransform){
215 SoTransform * t1 = VP1LinAlgUtils::toSoTransform(theSurface->transform());
216 t1->translation.setValue(p1.x(),p1.y(),p1.z());
217 errSimple->addChild( t1 );
218 errDetailed->addChild( t1 );
219 }
220 errSimple->addChild( ellipseGrp );
221 errDetailed->addChild( ellipseGrp );
222
223 return;
224}
225
226//____________________________________________________________________
227void VP1ErrorUtils::errorAtStraightLineSurface( SoSeparator* errSimple,
228 SoSeparator* errDetailed,
229 const AmgSymMatrix(5)& tmpcovmat,
230 const Amg::Vector2D& localPos,
231 const Trk::Surface* theSurface,
232 const double& sigmaScale,
233 const bool& drawZErrCircles,
234 const bool& drawCylinder,
235 int numNodes,
236 const bool& force1D,
237 const bool& addTransform)
238{
239 VP1Msg::messageVerbose("VP1ErrorUtils::errorAtStraightLineSurface()");
240
241 // const Trk::CovarianceMatrix& tmpcovmat = meas->localErrorMatrix().covariance();
242
243 // Global transform (To surface)
244 if (addTransform){
245 SoTransform * t1 = VP1LinAlgUtils::toSoTransform(theSurface->transform());
246 errDetailed->addChild( t1 );
247 errSimple->addChild( t1 );
248 }
249
250 const double sqrtv0 = sqrt( tmpcovmat(0,0) );
251 double sqrtv1=0.0;
252 if (!force1D){
253 sqrtv1 = sqrt( tmpcovmat(1,1) );
254 } else {
255 sqrtv1=100;//FIXME!
256 }
257 // Needed to get local position
258 //const Trk::AtaStraightLine * atas = dynamic_cast<const Trk::AtaStraightLine *>(m_pars);
259 // const Trk::AtaStraightLine * atas = dynamic_cast<const Trk::AtaStraightLine *>(meas);
260 // const Trk::Perigee * per = dynamic_cast<const Trk::Perigee *>(meas);
261 // if (!per&&!atas) return; //TODO Print error.
262 // const Amg::Vector2D& localPos = atas?atas->localPosition():per->localPosition();
263
264 const double radius = fabs(localPos[Trk::locR]);
265 const double rp = radius + sigmaScale * sqrtv0;
266 const double rm = radius - sigmaScale * sqrtv0;
267
268 // Local translation (To get the right Z position on the tube)
269 SoTranslation * t0 = new SoTranslation;
270 t0->translation.setValue(0,0,localPos[Trk::locZ]);
271
272 // draw circles
273 SoSeparator * circleGrp = new SoSeparator;
274 circleGrp->addChild(t0);
275
276 SoSeparator * circleGrpSimple = new SoSeparator;
277 circleGrpSimple->addChild(t0);
278
279 SoVertexProperty *vertices = new SoVertexProperty();
280 double zz[3];
281 int Nzz;
282 if ( drawZErrCircles )
283 {
284 Nzz = 3;
285 zz[0] = -sigmaScale * sqrtv1;
286 zz[1] = 0.0;
287 zz[2] = +sigmaScale * sqrtv1;
288 } else
289 {
290 Nzz = 1;
291 zz[0] = 0.0;
292 }
293
294 double rr[2];
295 int Nrr;
296 if ( rm > 0 )
297 {
298 Nrr = 2;
299 rr[0] = rp;
300 rr[1] = rm;
301 } else
302 {
303 Nrr = 1;
304 rr[0] = rp;
305 }
306
307 SoLineSet * circles = new SoLineSet();
308 SoLineSet * circlesSimple = new SoLineSet();
309 int iver(0);
310 int numlines(0);
311 int numlinesSimple(0);
312 for (int k = 0; k<Nrr; k++)
313 {
314 for (int j = 0; j<Nzz; j++)
315 {
316 vertices->vertex.set1Value(iver++,rr[k],0.0,zz[j]);
317 for (int i = 1; i < numNodes; i++)
318 {
319 vertices->vertex.set1Value(iver++,
320 cos(2.0*static_cast<double>(i)*M_PI/static_cast<double>(numNodes))*rr[k],
321 sin(2.0*static_cast<double>(i)*M_PI/static_cast<double>(numNodes))*rr[k],
322 zz[j]);
323 }
324 vertices->vertex.set1Value(iver++,rr[k],0.0,zz[j]);
325
326 circles->numVertices.set1Value(numlines++,numNodes+1);
327
328 if (k==0)
329 {
330 circlesSimple->numVertices.set1Value(numlinesSimple++,numNodes+1);
331 }
332 }
333 }
334 circles->vertexProperty = vertices;
335 circleGrp->addChild( circles );
336
337 circlesSimple->vertexProperty = vertices;
338 circleGrpSimple->addChild( circlesSimple );
339
340 errDetailed->addChild( circleGrp );
341 errSimple->addChild( circleGrpSimple );
342 // end of draw circles
343
344 if (drawCylinder) // Outer cylinder
345 {
346 SoCylinder * outerCyl = new SoCylinder;
347 outerCyl->removePart( SoCylinder::TOP );
348 outerCyl->removePart( SoCylinder::BOTTOM );
349 outerCyl->radius.setValue ( rp );
350 outerCyl->height.setValue ( 2.0 * sigmaScale * sqrtv1 );
351
352 SoSeparator * cylGrp = new SoSeparator;
353 cylGrp->addChild(t0);
354
355 SoGroup * outCylGrp = new SoGroup;
356 SoRotationXYZ * outCylRot = new SoRotationXYZ;
357 outCylRot->axis = SoRotationXYZ::X;
358 outCylRot->angle = M_PI_2;
359 outCylGrp->addChild(outCylRot);
360 outCylGrp->addChild(outerCyl);
361 cylGrp->addChild(outCylGrp);
362
364 SoTransparency * trans = new SoTransparency;
365 errDetailed->addChild( trans );
366 errDetailed->addChild( cylGrp );
367 }
368
369 return;
370}
371
372bool VP1ErrorUtils::covMatrixIsSane( const AmgCovMatrix& covmat)
373{
374 VP1Msg::messageVerbose("VP1ErrorUtils::covMatrixIsSane(AmgCovMatrix)");
375
376 // if (covmat.rows() > 2) VP1Msg::message("VP1ErrorUtils::covMatrixIsSane - covariance matrix is too big (>2)");
377 if (covmat.rows()!=covmat.cols()) VP1Msg::message("VP1ErrorUtils::covMatrixIsSane - covariance matrix is not symmetric");
378 for ( int row = 0; row < covmat.rows();row++){
379 for ( int col = 0; col < covmat.cols();col++){
380 if (covmat(row,col) != covmat(row,col)) return false; //NaN
381 }
382 }
383 return true;
384}
386{
387 VP1Msg::messageVerbose("VP1ErrorUtils::covMatrixIsSane(AmgSymMatrix(5))");
388
389 // if (covmat.rows() > 2) VP1Msg::message("VP1ErrorUtils::covMatrixIsSane - covariance matrix is too big (>2)");
390 if (covmat.rows()!=covmat.cols()) VP1Msg::message("VP1ErrorUtils::covMatrixIsSane - covariance matrix is not symmetric");
391 for ( int row = 0; row < covmat.rows();row++){
392 for ( int col = 0; col < covmat.cols();col++){
393 if (covmat(row,col) != covmat(row,col)) return false; //NaN
394 }
395 }
396 return true;
397}
const boost::regex rr(r_r)
#define M_PI
Scalar theta() const
theta method
#define gr
#define AmgSymMatrix(dim)
double length(const pvec &v)
ReadCards * rp
static Double_t t0
typedef AmgSymMatrix(2) AmgCovMatrix
static void initClass()
static const double surfaceThickness
Abstract Base Class for tracking surfaces.
const Amg::Transform3D & transform() const
Returns HepGeom::Transform3D by reference.
static void addSimple1DError(SoGroup *gr, const double &error, const double &sigmaScale, const double &length)
static void addRotatedErrorEllipse(SoGroup *gr, const AmgSymMatrix(5)&covmat, const double &sigmaScale, int numNodes=12, const double &translate=0.0, const bool &symmetric=false)
static bool covMatrixIsSane(const AmgCovMatrix &covmat)
returns false if there is a problem detected with the cov matrix
static void errorAtPlaneSurface(SoSeparator *errSimple, SoSeparator *errDetailed, const AmgSymMatrix(5)&tmpCovMat, const Trk::Surface *theSurface, const Amg::Vector3D &p1, const double &nStdDev=3.0, int numNodes=12, const bool &moveToSurface=false, const bool &force1D=false, const bool &addTransform=true)
static void errorAtStraightLineSurface(SoSeparator *errSimple, SoSeparator *errDetailed, const AmgSymMatrix(5)&tmpcovmat, const Amg::Vector2D &localPos, const Trk::Surface *theSurface, const double &nStdDev=3.0, const bool &drawZErrCircles=false, const bool &drawCylinder=false, int numNodes=12, const bool &force1D=false, const bool &addTransform=true)
static SoTransform * toSoTransform(const HepGeom::Transform3D &, SoTransform *t=0)
static void messageVerbose(const QString &)
Definition VP1Msg.cxx:84
static void message(const QString &, IVP1System *sys=0)
Definition VP1Msg.cxx:30
static SoNode * createEllipse(const double &radiusX, const double &radiusY, const int &numnodes=12)
Eigen::Matrix< double, 2, 1 > Vector2D
Eigen::Matrix< double, 3, 1 > Vector3D
@ locR
Definition ParamDefs.h:44
@ locZ
local cylindrical
Definition ParamDefs.h:42