ATLAS Offline Software
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 
20 #include "VP1Utils/VP1ErrorUtils.h"
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 
47 typedef AmgSymMatrix(2) AmgCovMatrix;
48 
49 
50 
51 
52 //____________________________________________________________________
53 void VP1ErrorUtils::addRotatedErrorEllipse( SoGroup* gr,
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 //____________________________________________________________________
172 void 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 //____________________________________________________________________
227 void 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 
372 bool 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 }
HitsSoNodeManager.h
VP1ErrorUtils.h
query_example.row
row
Definition: query_example.py:24
VP1ErrorUtils::covMatrixIsSane
static bool covMatrixIsSane(const AmgCovMatrix &covmat)
returns false if there is a problem detected with the cov matrix
Definition: VP1ErrorUtils.cxx:372
VP1QtInventorUtils::createEllipse
static SoNode * createEllipse(const double &radiusX, const double &radiusY, const int &numnodes=12)
Definition: VP1QtInventorUtils.cxx:1324
RectangleBounds.h
Surface.h
VP1ErrorUtils::addRotatedErrorEllipse
static void addRotatedErrorEllipse(SoGroup *gr, const AmgSymMatrix(5)&covmat, const double &sigmaScale, int numNodes=12, const double &translate=0.0, const bool &symmetric=false)
Definition: VP1ErrorUtils.cxx:53
SoTransparency
Definition: SoTransparency.h:20
Amg::Vector2D
Eigen::Matrix< double, 2, 1 > Vector2D
Definition: GeoPrimitives.h:48
Monitored::Z
@ Z
Definition: HistogramFillerUtils.h:24
VP1Msg.h
theta
Scalar theta() const
theta method
Definition: AmgMatrixBasePlugin.h:71
plotBeamSpotVxVal.covmat
covmat
Definition: plotBeamSpotVxVal.py:206
ALFA_EventTPCnv_Dict::t0
std::vector< ALFA_RawData_p1 > t0
Definition: ALFA_EventTPCnvDict.h:42
ALFA_EventTPCnv_Dict::t1
std::vector< ALFA_RawDataCollection_p1 > t1
Definition: ALFA_EventTPCnvDict.h:43
VP1ErrorUtils::errorAtPlaneSurface
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)
Definition: VP1ErrorUtils.cxx:172
M_PI
#define M_PI
Definition: ActiveFraction.h:11
AmgSymMatrix
typedef AmgSymMatrix(2) AmgCovMatrix
gr
#define gr
Trk::locR
@ locR
Definition: ParamDefs.h:50
drawFromPickle.cos
cos
Definition: drawFromPickle.py:36
const
bool const RAWDATA *ch2 const
Definition: LArRodBlockPhysicsV0.cxx:562
SoTransparency.h
LINES
bool LINES
Definition: computils.cxx:39
Monitored::X
@ X
Definition: HistogramFillerUtils.h:24
VP1QtInventorUtils.h
VP1ErrorUtils
Definition: VP1ErrorUtils.h:43
VP1LinAlgUtils.h
VP1ErrorUtils::addSimple1DError
static void addSimple1DError(SoGroup *gr, const double &error, const double &sigmaScale, const double &length)
Definition: VP1ErrorUtils.cxx:121
Trk::locZ
@ locZ
local cylindrical
Definition: ParamDefs.h:48
SoTransparency::initClass
static void initClass()
Definition: SoTransparency.cxx:29
parseMapping.v0
def v0
Definition: parseMapping.py:149
lumiFormat.i
int i
Definition: lumiFormat.py:92
SurfaceToSoNode::surfaceThickness
static const double surfaceThickness
Definition: SurfaceToSoNode.h:55
python.selection.number
number
Definition: selection.py:20
VP1Msg::messageVerbose
static void messageVerbose(const QString &)
Definition: VP1Msg.cxx:84
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
query_example.col
col
Definition: query_example.py:7
ParticleGun_SamplingFraction.radius
radius
Definition: ParticleGun_SamplingFraction.py:96
VP1Msg::message
static void message(const QString &, IVP1System *sys=0)
Definition: VP1Msg.cxx:30
rr
const boost::regex rr(r_r)
SurfaceToSoNode.h
drawFromPickle.sin
sin
Definition: drawFromPickle.py:36
rp
ReadCards * rp
Definition: IReadCards.cxx:26
Trk::Surface
Definition: Tracking/TrkDetDescr/TrkSurfaces/TrkSurfaces/Surface.h:75
VP1ErrorUtils::errorAtStraightLineSurface
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)
Definition: VP1ErrorUtils.cxx:227
error
Definition: IImpactPoint3dEstimator.h:70
Trk::Surface::transform
const Amg::Transform3D & transform() const
Returns HepGeom::Transform3D by reference.
VP1LinAlgUtils::toSoTransform
static SoTransform * toSoTransform(const HepGeom::Transform3D &, SoTransform *t=0)
Definition: VP1LinAlgUtils.cxx:40
length
double length(const pvec &v)
Definition: FPGATrackSimLLPDoubletHoughTransformTool.cxx:26
SoGenericBox.h
fitman.k
k
Definition: fitman.py:528