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