CMS 3D CMS Logo

CSCSegFit.cc
Go to the documentation of this file.
1 // CSCSegFit.cc
2 // Last mod: 03.02.2015
3 
5 
7 
9 
12 
13 
14 void CSCSegFit::fit(void) {
15  if ( fitdone() ) return; // don't redo fit unnecessarily
16  short n = nhits();
17  switch ( n ) {
18  case 1:
19  edm::LogVerbatim("CSCSegFit") << "[CSCSegFit::fit] - cannot fit just 1 hit!!";
20  break;
21  case 2:
22  fit2();
23  break;
24  case 3:
25  case 4:
26  case 5:
27  case 6:
28  fitlsq();
29  break;
30  default:
31  edm::LogVerbatim("CSCSegFit") << "[CSCSegFit::fit] - cannot fit more than 6 hits!!";
32  }
33 }
34 
35 void CSCSegFit::fit2(void) {
36 
37  // Just join the two points
38  // Equation of straight line between (x1, y1) and (x2, y2) in xy-plane is
39  // y = mx + c
40  // with m = (y2-y1)/(x2-x1)
41  // and c = (y1*x2-x2*y1)/(x2-x1)
42 
43  CSCSetOfHits::const_iterator ih = hits_.begin();
44  int il1 = (*ih)->cscDetId().layer();
45  const CSCRecHit2D& h1 = (**ih);
46  ++ih;
47  int il2 = (*ih)->cscDetId().layer();
48  const CSCRecHit2D& h2 = (**ih);
49 
50  // Skip if on same layer, but should be impossible :)
51  if (il1 == il2) {
52  edm::LogVerbatim("CSCSegFit") << "[CSCSegFit:fit]2 - 2 hits on same layer!!";
53  return;
54  }
55 
56  const CSCLayer* layer1 = chamber()->layer(il1);
57  const CSCLayer* layer2 = chamber()->layer(il2);
58 
59  GlobalPoint h1glopos = layer1->toGlobal(h1.localPosition());
60  GlobalPoint h2glopos = layer2->toGlobal(h2.localPosition());
61 
62  // We want hit wrt chamber (and local z will be != 0)
63  LocalPoint h1pos = chamber()->toLocal(h1glopos);
64  LocalPoint h2pos = chamber()->toLocal(h2glopos);
65 
66  float dz = h2pos.z()-h1pos.z();
67 
68  uslope_ = ( h2pos.x() - h1pos.x() ) / dz ;
69  vslope_ = ( h2pos.y() - h1pos.y() ) / dz ;
70 
71  float uintercept = ( h1pos.x()*h2pos.z() - h2pos.x()*h1pos.z() ) / dz;
72  float vintercept = ( h1pos.y()*h2pos.z() - h2pos.y()*h1pos.z() ) / dz;
73  intercept_ = LocalPoint( uintercept, vintercept, 0.);
74 
75  setOutFromIP();
76 
77  //@@ NOT SURE WHAT IS SENSIBLE FOR THESE...
78  chi2_ = 0.;
79  ndof_ = 0;
80 
81  fitdone_ = true;
82 }
83 
84 
85 void CSCSegFit::fitlsq(void) {
86 
87  // Linear least-squares fit to up to 6 CSC rechits, one per layer in a CSC.
88  // Comments adapted from mine in original CSCSegAlgoSK algorithm.
89 
90  // Fit to the local x, y rechit coordinates in z projection
91  // The strip measurement controls the precision of x
92  // The wire measurement controls the precision of y.
93  // Typical precision: u (strip, sigma~200um), v (wire, sigma~1cm)
94 
95  // Set up the normal equations for the least-squares fit as a matrix equation
96 
97  // We have a vector of measurements m, which is a 2n x 1 dim matrix
98  // The transpose mT is (u1, v1, u2, v2, ..., un, vn) where
99  // ui is the strip-associated measurement and
100  // vi is the wire-associated measurement
101  // for a given rechit i.
102 
103  // The fit is to
104  // u = u0 + uz * z
105  // v = v0 + vz * z
106  // where u0, uz, v0, vz are the parameters to be obtained from the fit.
107 
108  // These are contained in a vector p which is a 4x1 dim matrix, and
109  // its transpose pT is (u0, v0, uz, vz). Note the ordering!
110 
111  // The covariance matrix for each pair of measurements is 2 x 2 and
112  // the inverse of this is the error matrix E.
113  // The error matrix for the whole set of n measurements is a diagonal
114  // matrix with diagonal elements the individual 2 x 2 error matrices
115  // (because the inverse of a diagonal matrix is a diagonal matrix
116  // with each element the inverse of the original.)
117 
118  // In function 'weightMatrix()', the variable 'matrix' is filled with this
119  // block-diagonal overall covariance matrix. Then 'matrix' is inverted to the
120  // block-diagonal error matrix, and returned.
121 
122  // Define the matrix A as
123  // 1 0 z1 0
124  // 0 1 0 z1
125  // 1 0 z2 0
126  // 0 1 0 z2
127  // .. .. .. ..
128  // 1 0 zn 0
129  // 0 1 0 zn
130 
131  // This matrix A is set up and returned by function 'derivativeMatrix()'.
132 
133  // Then the normal equations are described by the matrix equation
134  //
135  // (AT E A)p = (AT E)m
136  //
137  // where AT is the transpose of A.
138 
139  // Call the combined matrix on the LHS, M, and that on the RHS, B:
140  // M p = B
141 
142  // We solve this for the parameter vector, p.
143  // The elements of M and B then involve sums over the hits
144 
145  // The covariance matrix of the parameters is obtained by
146  // (AT E A)^-1 calculated in 'covarianceMatrix()'.
147 
148 
149  // NOTE
150  // We need local position of a RecHit w.r.t. the CHAMBER
151  // and the RecHit itself only knows its local position w.r.t.
152  // the LAYER, so we must explicitly transform global position.
153 
154 
155  SMatrix4 M; // 4x4, init to 0
156  SVector4 B; // 4x1, init to 0;
157 
158  CSCSetOfHits::const_iterator ih = hits_.begin();
159 
160  for (ih = hits_.begin(); ih != hits_.end(); ++ih) {
161  const CSCRecHit2D& hit = (**ih);
162  const CSCLayer* layer = chamber()->layer(hit.cscDetId().layer());
163  GlobalPoint gp = layer->toGlobal(hit.localPosition());
164  LocalPoint lp = chamber()->toLocal(gp);
165 
166  // Local position of hit w.r.t. chamber
167  double u = lp.x();
168  double v = lp.y();
169  double z = lp.z();
170 
171  // Covariance matrix of local errors
172  SMatrixSym2 IC; // 2x2, init to 0
173 
174  IC(0,0) = hit.localPositionError().xx();
175  IC(1,1) = hit.localPositionError().yy();
176  //@@ NOT SURE WHICH OFF-DIAGONAL ELEMENT MUST BE DEFINED BUT (1,0) WORKS
177  //@@ (and SMatrix enforces symmetry)
178  IC(1,0) = hit.localPositionError().xy();
179  // IC(0,1) = IC(1,0);
180 
181  // Invert covariance matrix (and trap if it fails!)
182  bool ok = IC.Invert();
183  if ( !ok ) {
184  edm::LogVerbatim("CSCSegment|CSCSegFit") << "[CSCSegFit::fit] Failed to invert covariance matrix: \n" << IC;
185  // return ok; //@@ SHOULD PASS THIS BACK TO CALLER?
186  }
187 
188  M(0,0) += IC(0,0);
189  M(0,1) += IC(0,1);
190  M(0,2) += IC(0,0) * z;
191  M(0,3) += IC(0,1) * z;
192  B(0) += u * IC(0,0) + v * IC(0,1);
193 
194  M(1,0) += IC(1,0);
195  M(1,1) += IC(1,1);
196  M(1,2) += IC(1,0) * z;
197  M(1,3) += IC(1,1) * z;
198  B(1) += u * IC(1,0) + v * IC(1,1);
199 
200  M(2,0) += IC(0,0) * z;
201  M(2,1) += IC(0,1) * z;
202  M(2,2) += IC(0,0) * z * z;
203  M(2,3) += IC(0,1) * z * z;
204  B(2) += ( u * IC(0,0) + v * IC(0,1) ) * z;
205 
206  M(3,0) += IC(1,0) * z;
207  M(3,1) += IC(1,1) * z;
208  M(3,2) += IC(1,0) * z * z;
209  M(3,3) += IC(1,1) * z * z;
210  B(3) += ( u * IC(1,0) + v * IC(1,1) ) * z;
211 
212  }
213 
214  SVector4 p;
215  bool ok = M.Invert();
216  if (!ok ){
217  edm::LogVerbatim("CSCSegment|CSCSegFit") << "[CSCSegFit::fit] Failed to invert matrix: \n" << M;
218  // return ok; //@@ SHOULD PASS THIS BACK TO CALLER?
219  }
220  else {
221  p = M * B;
222  }
223 
224  // LogTrace("CSCSegFit") << "[CSCSegFit::fit] p = "
225  // << p(0) << ", " << p(1) << ", " << p(2) << ", " << p(3);
226 
227  // fill member variables (note origin has local z = 0)
228  // intercept_
229  intercept_ = LocalPoint(p(0), p(1), 0.);
230 
231  // localdir_ - set so segment points outwards from IP
232  uslope_ = p(2);
233  vslope_ = p(3);
234  setOutFromIP();
235 
236  // calculate chi2 of fit
237  setChi2( );
238 
239  // flag fit has been done
240  fitdone_ = true;
241 
242 }
243 
244 
245 
246 void CSCSegFit::setChi2(void) {
247 
248  double chsq = 0.;
249 
250  CSCSetOfHits::const_iterator ih;
251  for (ih = hits_.begin(); ih != hits_.end(); ++ih) {
252 
253  const CSCRecHit2D& hit = (**ih);
254  const CSCLayer* layer = chamber()->layer(hit.cscDetId().layer());
255  GlobalPoint gp = layer->toGlobal(hit.localPosition());
256  LocalPoint lp = chamber()->toLocal(gp);
257 
258  double u = lp.x();
259  double v = lp.y();
260  double z = lp.z();
261 
262  double du = intercept_.x() + uslope_ * z - u;
263  double dv = intercept_.y() + vslope_ * z - v;
264 
265  // LogTrace("CSCSegFit") << "[CSCSegFit::setChi2] u, v, z = " << u << ", " << v << ", " << z;
266 
267  SMatrixSym2 IC; // 2x2, init to 0
268 
269  IC(0,0) = hit.localPositionError().xx();
270  // IC(0,1) = hit.localPositionError().xy();
271  IC(1,0) = hit.localPositionError().xy();
272  IC(1,1) = hit.localPositionError().yy();
273  // IC(1,0) = IC(0,1);
274 
275  // LogTrace("CSCSegFit") << "[CSCSegFit::setChi2] IC before = \n" << IC;
276 
277  // Invert covariance matrix
278  bool ok = IC.Invert();
279  if (!ok ){
280  edm::LogVerbatim("CSCSegment|CSCSegFit") << "[CSCSegFit::setChi2] Failed to invert covariance matrix: \n" << IC;
281  // return ok;
282  }
283  // LogTrace("CSCSegFit") << "[CSCSegFit::setChi2] IC after = \n" << IC;
284  chsq += du*du*IC(0,0) + 2.*du*dv*IC(0,1) + dv*dv*IC(1,1);
285  }
286 
287  // fill member variables
288  chi2_ = chsq;
289  ndof_ = 2.*hits_.size() - 4;
290 
291  // LogTrace("CSCSegFit") << "[CSCSegFit::setChi2] chi2 = " << chi2_ << "/" << ndof_ << " dof";
292 
293 }
294 
295 
296 
297 
299 
300  bool ok = true;
301 
302  SMatrixSym12 matrix = ROOT::Math::SMatrixIdentity(); // 12x12, init to 1's on diag
303 
304  int row = 0;
305 
306  for (CSCSetOfHits::const_iterator it = hits_.begin(); it != hits_.end(); ++it) {
307 
308  const CSCRecHit2D& hit = (**it);
309 
310 // Note scaleXError allows rescaling the x error if necessary
311 
312  matrix(row, row) = scaleXError()*hit.localPositionError().xx();
313  matrix(row, row+1) = hit.localPositionError().xy();
314  ++row;
315  matrix(row, row-1) = hit.localPositionError().xy();
316  matrix(row, row) = hit.localPositionError().yy();
317  ++row;
318  }
319 
320  ok = matrix.Invert(); // invert in place
321  if ( !ok ) {
322  edm::LogVerbatim("CSCSegment|CSCSegFit") << "[CSCSegFit::weightMatrix] Failed to invert matrix: \n" << matrix;
323  // return ok; //@@ SHOULD PASS THIS BACK TO CALLER?
324  }
325  return matrix;
326 }
327 
328 
329 
330 
332 
333  SMatrix12by4 matrix; // 12x4, init to 0
334  int row = 0;
335 
336  for( CSCSetOfHits::const_iterator it = hits_.begin(); it != hits_.end(); ++it) {
337 
338  const CSCRecHit2D& hit = (**it);
339  const CSCLayer* layer = chamber()->layer(hit.cscDetId().layer());
340  GlobalPoint gp = layer->toGlobal(hit.localPosition());
341  LocalPoint lp = chamber()->toLocal(gp);
342  float z = lp.z();
343 
344  matrix(row, 0) = 1.;
345  matrix(row, 2) = z;
346  ++row;
347  matrix(row, 1) = 1.;
348  matrix(row, 3) = z;
349  ++row;
350  }
351  return matrix;
352 }
353 
354 
356  // Set direction of segment to point from IP outwards
357  // (Incorrect for particles not coming from IP, of course.)
358 
359  double dxdz = uslope_;
360  double dydz = vslope_;
361  double dz = 1./sqrt(1. + dxdz*dxdz + dydz*dydz);
362  double dx = dz*dxdz;
363  double dy = dz*dydz;
364  LocalVector localDir(dx,dy,dz);
365 
366  // localDir sometimes needs a sign flip
367  // Examine its direction and origin in global z: to point outward
368  // the localDir should always have same sign as global z...
369 
370  double globalZpos = ( chamber()->toGlobal( intercept_ ) ).z();
371  double globalZdir = ( chamber()->toGlobal( localDir ) ).z();
372  double directionSign = globalZpos * globalZdir;
373  localdir_ = (directionSign * localDir ).unit();
374 }
375 
376 
377 
379 
382  // LogTrace("CSCSegFit") << "[CSCSegFit::covarianceMatrix] weights matrix W: \n" << weights;
383  // LogTrace("CSCSegFit") << "[CSCSegFit::covarianceMatrix] derivatives matrix A: \n" << A;
384 
385  // (AT W A)^-1
386  // e.g. See http://www.phys.ufl.edu/~avery/fitting.html, part I
387 
388  bool ok;
389  SMatrixSym4 result = ROOT::Math::SimilarityT(A, weights);
390  // LogTrace("CSCSegFit") << "[CSCSegFit::covarianceMatrix] (AT W A): \n" << result;
391  ok = result.Invert(); // inverts in place
392  if ( !ok ) {
393  edm::LogVerbatim("CSCSegment|CSCSegFit") << "[CSCSegFit::calculateError] Failed to invert matrix: \n" << result;
394  // return ok; //@@ SHOULD PASS THIS BACK TO CALLER?
395  }
396  // LogTrace("CSCSegFit") << "[CSCSegFit::covarianceMatrix] (AT W A)^-1: \n" << result;
397 
398  // reorder components to match TrackingRecHit interface (CSCSegment isa TrackingRecHit)
399  // i.e. slopes first, then positions
400  AlgebraicSymMatrix flipped = flipErrors( result );
401 
402  return flipped;
403 }
404 
405 
407 
408  // The CSCSegment needs the error matrix re-arranged to match
409  // parameters in order (uz, vz, u0, v0)
410  // where uz, vz = slopes, u0, v0 = intercepts
411 
412  // LogTrace("CSCSegFit") << "[CSCSegFit::flipErrors] input: \n" << a;
413 
414  AlgebraicSymMatrix hold(4, 0. );
415 
416  for ( short j=0; j!=4; ++j) {
417  for (short i=0; i!=4; ++i) {
418  hold(i+1,j+1) = a(i,j); // SMatrix counts from 0, AlgebraicMatrix from 1
419  }
420  }
421 
422  // LogTrace("CSCSegFit") << "[CSCSegFit::flipErrors] after copy:";
423  // LogTrace("CSCSegFit") << "(" << hold(1,1) << " " << hold(1,2) << " " << hold(1,3) << " " << hold(1,4);
424  // LogTrace("CSCSegFit") << " " << hold(2,1) << " " << hold(2,2) << " " << hold(2,3) << " " << hold(2,4);
425  // LogTrace("CSCSegFit") << " " << hold(3,1) << " " << hold(3,2) << " " << hold(3,3) << " " << hold(3,4);
426  // LogTrace("CSCSegFit") << " " << hold(4,1) << " " << hold(4,2) << " " << hold(4,3) << " " << hold(4,4) << ")";
427 
428  // errors on slopes into upper left
429  hold(1,1) = a(2,2);
430  hold(1,2) = a(2,3);
431  hold(2,1) = a(3,2);
432  hold(2,2) = a(3,3);
433 
434  // errors on positions into lower right
435  hold(3,3) = a(0,0);
436  hold(3,4) = a(0,1);
437  hold(4,3) = a(1,0);
438  hold(4,4) = a(1,1);
439 
440  // must also interchange off-diagonal elements of off-diagonal 2x2 submatrices
441  hold(4,1) = a(1,2);
442  hold(3,2) = a(0,3);
443  hold(2,3) = a(3,0); // = a(0,3)
444  hold(1,4) = a(2,1); // = a(1,2)
445 
446  // LogTrace("CSCSegFit") << "[CSCSegFit::flipErrors] after flip:";
447  // LogTrace("CSCSegFit") << "(" << hold(1,1) << " " << hold(1,2) << " " << hold(1,3) << " " << hold(1,4);
448  // LogTrace("CSCSegFit") << " " << hold(2,1) << " " << hold(2,2) << " " << hold(2,3) << " " << hold(2,4);
449  // LogTrace("CSCSegFit") << " " << hold(3,1) << " " << hold(3,2) << " " << hold(3,3) << " " << hold(3,4);
450  // LogTrace("CSCSegFit") << " " << hold(4,1) << " " << hold(4,2) << " " << hold(4,3) << " " << hold(4,4) << ")";
451 
452  return hold;
453 }
454 
455 float CSCSegFit::xfit( float z ) const {
456  //@@ ADD THIS TO EACH ACCESSOR OF FIT RESULTS?
457  // if ( !fitdone() ) fit();
458  return intercept_.x() + uslope_ * z;
459 }
460 
461 float CSCSegFit::yfit( float z ) const {
462  return intercept_.y() + vslope_ * z;
463 }
464 
465 float CSCSegFit::xdev( float x, float z ) const {
466  return intercept_.x() + uslope_ * z - x;
467 }
468 
469 float CSCSegFit::ydev( float y, float z ) const {
470  return intercept_.y() + vslope_ * z - y;
471 }
472 
473 float CSCSegFit::Rdev(float x, float y, float z) const {
474  return sqrt ( xdev(x,z)*xdev(x,z) + ydev(y,z)*ydev(y,z) );
475 }
476 
LocalPoint intercept_
Definition: CSCSegFit.h:118
void fit(void)
Definition: CSCSegFit.cc:14
float xx() const
Definition: LocalError.h:24
Point3DBase< Scalar, LocalTag > LocalPoint
Definition: Definitions.h:32
CSCDetId cscDetId() const
Definition: CSCRecHit2D.h:52
void fit2(void)
Definition: CSCSegFit.cc:35
LocalVector localdir_
Definition: CSCSegFit.h:119
void fitlsq(void)
Definition: CSCSegFit.cc:85
double_binary B
Definition: DDStreamer.cc:248
ROOT::Math::SMatrix< double, 12, 4 > SMatrix12by4
Definition: CSCSegFit.h:42
GlobalPoint toGlobal(const Local2DPoint &lp) const
Conversion to the global R.F. from the R.F. of the GeomDet.
Definition: GeomDet.h:54
AlgebraicSymMatrix flipErrors(const SMatrixSym4 &)
Definition: CSCSegFit.cc:406
double chi2_
Definition: CSCSegFit.h:120
T y() const
Definition: PV3DBase.h:63
float vslope_
Definition: CSCSegFit.h:117
float Rdev(float x, float y, float z) const
Definition: CSCSegFit.cc:473
LocalPoint toLocal(const GlobalPoint &gp) const
Conversion to the R.F. of the GeomDet.
Definition: GeomDet.h:69
int layer() const
Definition: CSCDetId.h:61
bool fitdone() const
Definition: CSCSegFit.h:90
size_t nhits(void) const
Definition: CSCSegFit.h:84
float xy() const
Definition: LocalError.h:25
LocalError localPositionError() const
Definition: CSCRecHit2D.h:51
float yy() const
Definition: LocalError.h:26
T sqrt(T t)
Definition: SSEVec.h:18
ROOT::Math::SMatrix< double, 4, 4, ROOT::Math::MatRepSym< double, 4 > > SMatrixSym4
Definition: CSCSegFit.h:46
T z() const
Definition: PV3DBase.h:64
bool fitdone_
Definition: CSCSegFit.h:123
ROOT::Math::SVector< double, 4 > SVector4
Definition: CSCSegFit.h:52
const CSCLayer * layer(CSCDetId id) const
Return the layer corresponding to the given id.
Definition: CSCChamber.cc:39
float xfit(float z) const
Definition: CSCSegFit.cc:455
ROOT::Math::SMatrix< double, 12, 12, ROOT::Math::MatRepSym< double, 12 > > SMatrixSym12
Definition: CSCSegFit.h:39
CSCSetOfHits hits_
Definition: CSCSegFit.h:115
float xdev(float x, float z) const
Definition: CSCSegFit.cc:465
ROOT::Math::SMatrix< double, 4 > SMatrix4
Definition: CSCSegFit.h:45
AlgebraicSymMatrix covarianceMatrix(void)
Definition: CSCSegFit.cc:378
void setOutFromIP(void)
Definition: CSCSegFit.cc:355
float ydev(float y, float z) const
Definition: CSCSegFit.cc:469
const CSCChamber * chamber() const
Definition: CSCSegFit.h:89
SMatrixSym12 weightMatrix(void)
Definition: CSCSegFit.cc:298
SMatrix12by4 derivativeMatrix(void)
Definition: CSCSegFit.cc:331
double a
Definition: hdecay.h:121
CLHEP::HepSymMatrix AlgebraicSymMatrix
ROOT::Math::SMatrix< double, 2, 2, ROOT::Math::MatRepSym< double, 2 > > SMatrixSym2
Definition: CSCSegFit.h:49
LocalPoint localPosition() const
Definition: CSCRecHit2D.h:50
T x() const
Definition: PV3DBase.h:62
float uslope_
Definition: CSCSegFit.h:116
int ndof_
Definition: CSCSegFit.h:121
double scaleXError(void) const
Definition: CSCSegFit.h:83
void setChi2(void)
Definition: CSCSegFit.cc:246
float yfit(float z) const
Definition: CSCSegFit.cc:461