CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
CSCSegAlgoShowering.cc
Go to the documentation of this file.
1 
11 
15 
18 
19 #include <algorithm>
20 #include <cmath>
21 #include <iostream>
22 #include <string>
23 
24 
25 /* Constructor
26  *
27  */
29 // debug = ps.getUntrackedParameter<bool>("CSCSegmentDebug");
30  dRPhiFineMax = ps.getParameter<double>("dRPhiFineMax");
31  dPhiFineMax = ps.getParameter<double>("dPhiFineMax");
32  tanThetaMax = ps.getParameter<double>("tanThetaMax");
33  tanPhiMax = ps.getParameter<double>("tanPhiMax");
34  maxRatioResidual = ps.getParameter<double>("maxRatioResidualPrune");
35 // maxDR = ps.getParameter<double>("maxDR");
36  maxDTheta = ps.getParameter<double>("maxDTheta");
37  maxDPhi = ps.getParameter<double>("maxDPhi");
38 }
39 
40 
41 /* Destructor:
42  *
43  */
45 
46 }
47 
48 
49 /* showerSeg
50  *
51  */
53 
54  theChamber = aChamber;
55  // Initialize parameters
56  std::vector<float> x, y, gz;
57  std::vector<int> n;
58 
59 
60  for (int i = 0; i < 6; ++i) {
61  x.push_back(0.);
62  y.push_back(0.);
63  gz.push_back(0.);
64  n.push_back(0);
65  }
66 
67  // Loop over hits to find center-of-mass position in each layer
68  for (ChamberHitContainer::const_iterator it = rechits.begin(); it != rechits.end(); it++ ) {
69  const CSCRecHit2D& hit = (**it);
70  const CSCDetId id = hit.cscDetId();
71  int l_id = id.layer();
72  const CSCLayer* layer = theChamber->layer(hit.cscDetId().layer());
73  GlobalPoint gp = layer->toGlobal(hit.localPosition());
74  LocalPoint lp = theChamber->toLocal(gp);
75 
76  n[l_id -1]++;
77  x[l_id -1] += lp.x();
78  y[l_id -1] += lp.y();
79  gz[l_id -1] += gp.z();
80  }
81 
82 
83  // Determine center of mass for each layer and average center of mass for chamber
84  float avgChamberX = 0.;
85  float avgChamberY = 0.;
86  int n_lay = 0;
87 
88  for (unsigned i = 0; i < 6; ++i) {
89  if (n[i] < 1 ) continue;
90 
91  x[i] = x[i]/n[i];
92  y[i] = y[i]/n[i];
93  avgChamberX += x[i];
94  avgChamberY += y[i];
95  n_lay++;
96 
97  }
98 
99  if ( n_lay > 0) {
100  avgChamberX = avgChamberX / n_lay;
101  avgChamberY = avgChamberY / n_lay;
102  }
103 
104  // Create a FakeSegment origin that points back to the IP
105  // Keep all this in global coordinates until last minute to avoid screwing up +/- signs !
106 
107  LocalPoint lpCOM(avgChamberX, avgChamberY, 0.);
108  GlobalPoint gpCOM = theChamber->toGlobal(lpCOM);
109  GlobalVector gvCOM(gpCOM.x(), gpCOM.y(), gpCOM.z());
110 
111  float Gdxdz = gpCOM.x()/gpCOM.z();
112  float Gdydz = gpCOM.y()/gpCOM.z();
113 
114  // Figure out the intersection of this vector with each layer of the chamber
115  // by projecting the vector
116  std::vector<LocalPoint> layerPoints;
117 
118  for (unsigned i = 1; i < 7; i++) {
119  // Get the layer z coordinates in global frame
120  const CSCLayer* layer = theChamber->layer(i);
121  LocalPoint temp(0., 0., 0.);
122  GlobalPoint gp = layer->toGlobal(temp);
123  float layer_Z = gp.z();
124 
125  // Then compute interesection of vector with that plane
126  float layer_X = Gdxdz * layer_Z;
127  float layer_Y = Gdydz * layer_Z;
128  GlobalPoint Gintersect(layer_X, layer_Y, layer_Z);
129  LocalPoint Lintersect = theChamber->toLocal(Gintersect);
130 
131  float layerX = Lintersect.x();
132  float layerY = Lintersect.y();
133  float layerZ = Lintersect.z();
134  LocalPoint layerPoint(layerX, layerY, layerZ);
135  layerPoints.push_back(layerPoint);
136  }
137 
138 
139  std::vector<float> r_closest;
140  std::vector<int> id;
141  for (unsigned i = 0; i < 6; ++i ) {
142  id.push_back(-1);
143  r_closest.push_back(9999.);
144  }
145 
146  int idx = 0;
147 
148  // Loop over all hits and find hit closest to com for that layer.
149  for (ChamberHitContainer::const_iterator it = rechits.begin(); it != rechits.end(); it++ ) {
150  const CSCRecHit2D& hit = (**it);
151  int layId = hit.cscDetId().layer();
152  const CSCLayer* layer = theChamber->layer(hit.cscDetId().layer());
153  GlobalPoint gp = layer->toGlobal(hit.localPosition());
154  LocalPoint lp = theChamber->toLocal(gp);
155 
156  float d_x = lp.x() - layerPoints[layId-1].x();
157  float d_y = lp.y() - layerPoints[layId-1].y();
158 
159  LocalPoint diff(d_x, d_y, 0.);
160 
161  if ( fabs(diff.mag() ) < r_closest[layId-1] ) {
162  r_closest[layId-1] = fabs(diff.mag());
163  id[layId-1] = idx;
164  }
165  idx++;
166  }
167 
168  // Now fill vector of rechits closest to center of mass:
169  protoSegment.clear();
170  idx = 0;
171 
172  // Loop over all hits and find hit closest to com for that layer.
173  for (ChamberHitContainer::const_iterator it = rechits.begin(); it != rechits.end(); it++ ) {
174  const CSCRecHit2D& hit = (**it);
175  int layId = hit.cscDetId().layer();
176 
177  if ( idx == id[layId-1] )protoSegment.push_back(*it);
178 
179  idx++;
180  }
181 
182  // Reorder hits in protosegment
183  if ( gz[0] > 0. ) {
184  if ( gz[0] > gz[5] ) {
185  reverse( protoSegment.begin(), protoSegment.end() );
186  }
187  }
188  else if ( gz[0] < 0. ) {
189  if ( gz[0] < gz[5] ) {
190  reverse( protoSegment.begin(), protoSegment.end() );
191  }
192  }
193 
194 
195  // Compute the segment properties
197 
198  // Clean up protosegment if there is one very bad hit on segment
199  if (protoSegment.size() > 4) pruneFromResidual();
200 
201  // Look for better hits near segment
202  for (ChamberHitContainer::const_iterator it = rechits.begin(); it != rechits.end(); it++ ) {
203 
204  const CSCRecHit2D* h = *it;
205  int layer = h->cscDetId().layer();
206 
207  if ( isHitNearSegment( h ) ) compareProtoSegment(h, layer);
208  }
209 
210  // Prune worse hit if necessary
211  if ( protoSegment.size() > 5 ) pruneFromResidual();
212 
213  // Update the parameters
215 
216  // Local direction
217  double dz = 1./sqrt(1. + protoSlope_u*protoSlope_u + protoSlope_v*protoSlope_v);
218  double dx = dz*protoSlope_u;
219  double dy = dz*protoSlope_v;
220  LocalVector localDir(dx,dy,dz);
221 
222  // localDir may need sign flip to ensure it points outward from IP
223  double globalZpos = ( theChamber->toGlobal( protoIntercept ) ).z();
224  double globalZdir = ( theChamber->toGlobal( localDir ) ).z();
225  double directionSign = globalZpos * globalZdir;
226  LocalVector protoDirection = (directionSign * localDir).unit();
227 
228  // Check to make sure the fitting didn't fuck things up
229  GlobalVector protoGlobalDir = theChamber->toGlobal( protoDirection );
230  double protoTheta = protoGlobalDir.theta();
231  double protoPhi = protoGlobalDir.phi();
232  double simTheta = gvCOM.theta();
233  double simPhi = gvCOM.phi();
234 
235  float dTheta = fabs(protoTheta - simTheta);
236  float dPhi = fabs(protoPhi - simPhi);
237  // float dR = sqrt(dEta*dEta + dPhi*dPhi);
238 
239  // Error matrix
240  AlgebraicSymMatrix protoErrors = calculateError();
241  // but reorder components to match what's required by TrackingRecHit interface
242  // i.e. slopes first, then positions
243  flipErrors( protoErrors );
244 
245  //Flag the segment with chi12 of -1 of the segment isn't pointing toward origin
246  if (dTheta > maxDTheta || dPhi > maxDPhi) {
247  CSCSegment temp(protoSegment, protoIntercept, protoDirection, protoErrors, -1);
248  return temp;
249  }
250  else {
251  CSCSegment temp(protoSegment, protoIntercept, protoDirection, protoErrors, protoChi2);
252  return temp;
253  }
254 
255 }
256 
257 
258 
259 
260 /* isHitNearSegment
261  *
262  * Compare rechit with expected position from proto_segment
263  */
265 
266  const CSCLayer* layer = theChamber->layer(hit->cscDetId().layer());
267 
268  // hit phi position in global coordinates
269  GlobalPoint Hgp = layer->toGlobal(hit->localPosition());
270  double Hphi = Hgp.phi();
271  if (Hphi < 0.) Hphi += 2.*M_PI;
272  LocalPoint Hlp = theChamber->toLocal(Hgp);
273  double z = Hlp.z();
274 
275  double LocalX = protoIntercept.x() + protoSlope_u * z;
276  double LocalY = protoIntercept.y() + protoSlope_v * z;
277  LocalPoint Slp(LocalX, LocalY, z);
278  GlobalPoint Sgp = theChamber->toGlobal(Slp);
279  double Sphi = Sgp.phi();
280  if (Sphi < 0.) Sphi += 2.*M_PI;
281  double R = sqrt(Sgp.x()*Sgp.x() + Sgp.y()*Sgp.y());
282 
283  double deltaPhi = Sphi - Hphi;
284  if (deltaPhi > 2.*M_PI) deltaPhi -= 2.*M_PI;
285  if (deltaPhi < -2.*M_PI) deltaPhi += 2.*M_PI;
286  if (deltaPhi < 0.) deltaPhi = -deltaPhi;
287 
288  double RdeltaPhi = R * deltaPhi;
289 
290  if (RdeltaPhi < dRPhiFineMax && deltaPhi < dPhiFineMax ) return true;
291 
292  return false;
293 }
294 
295 
296 /* Method addHit
297  *
298  * Test if can add hit to proto segment. If so, try to add it.
299  *
300  */
301 bool CSCSegAlgoShowering::addHit(const CSCRecHit2D* aHit, int layer) {
302 
303  // Return true if hit was added successfully and then parameters are updated.
304  // Return false if there is already a hit on the same layer, or insert failed.
305 
306  bool ok = true;
307 
308  // Test that we are not trying to add the same hit again
309  for ( ChamberHitContainer::const_iterator it = protoSegment.begin(); it != protoSegment.end(); it++ )
310  if ( aHit == (*it) ) return false;
311 
312  protoSegment.push_back(aHit);
313 
314  return ok;
315 }
316 
317 
318 /* Method updateParameters
319  *
320  * Perform a simple Least Square Fit on proto segment to determine slope and intercept
321  *
322  */
324 
325  // Compute slope from Least Square Fit
326  CLHEP::HepMatrix M(4,4,0);
327  CLHEP::HepVector B(4,0);
328 
329  ChamberHitContainer::const_iterator ih;
330 
331  for (ih = protoSegment.begin(); ih != protoSegment.end(); ++ih) {
332 
333  const CSCRecHit2D& hit = (**ih);
334  const CSCLayer* layer = theChamber->layer(hit.cscDetId().layer());
335  GlobalPoint gp = layer->toGlobal(hit.localPosition());
336  LocalPoint lp = theChamber->toLocal(gp);
337 
338  double u = lp.x();
339  double v = lp.y();
340  double z = lp.z();
341 
342  // ptc: Covariance matrix of local errors
343  CLHEP::HepMatrix IC(2,2);
344  IC(1,1) = hit.localPositionError().xx();
345  IC(1,2) = hit.localPositionError().xy();
346  IC(2,2) = hit.localPositionError().yy();
347  IC(2,1) = IC(1,2); // since Cov is symmetric
348 
349  // ptc: Invert covariance matrix (and trap if it fails!)
350  int ierr = 0;
351  IC.invert(ierr); // inverts in place
352  if (ierr != 0) {
353  LogDebug("CSC") << "CSCSegment::fitSlopes: failed to invert covariance matrix=\n" << IC << "\n";
354  }
355 
356  M(1,1) += IC(1,1);
357  M(1,2) += IC(1,2);
358  M(1,3) += IC(1,1) * z;
359  M(1,4) += IC(1,2) * z;
360  B(1) += u * IC(1,1) + v * IC(1,2);
361 
362  M(2,1) += IC(2,1);
363  M(2,2) += IC(2,2);
364  M(2,3) += IC(2,1) * z;
365  M(2,4) += IC(2,2) * z;
366  B(2) += u * IC(2,1) + v * IC(2,2);
367 
368  M(3,1) += IC(1,1) * z;
369  M(3,2) += IC(1,2) * z;
370  M(3,3) += IC(1,1) * z * z;
371  M(3,4) += IC(1,2) * z * z;
372  B(3) += ( u * IC(1,1) + v * IC(1,2) ) * z;
373 
374  M(4,1) += IC(2,1) * z;
375  M(4,2) += IC(2,2) * z;
376  M(4,3) += IC(2,1) * z * z;
377  M(4,4) += IC(2,2) * z * z;
378  B(4) += ( u * IC(2,1) + v * IC(2,2) ) * z;
379  }
380 
381  CLHEP::HepVector p = solve(M, B);
382 
383  // Update member variables
384  // Note that origin has local z = 0
385 
386  protoIntercept = LocalPoint(p(1), p(2), 0.);
387  protoSlope_u = p(3);
388  protoSlope_v = p(4);
389 
390  // Determine Chi^2 for the proto wire segment
391 
392  double chsq = 0.;
393 
394  for (ih = protoSegment.begin(); ih != protoSegment.end(); ++ih) {
395 
396  const CSCRecHit2D& hit = (**ih);
397  const CSCLayer* layer = theChamber->layer(hit.cscDetId().layer());
398  GlobalPoint gp = layer->toGlobal(hit.localPosition());
399  LocalPoint lp = theChamber->toLocal(gp);
400 
401  double u = lp.x();
402  double v = lp.y();
403  double z = lp.z();
404 
405  double du = protoIntercept.x() + protoSlope_u * z - u;
406  double dv = protoIntercept.y() + protoSlope_v * z - v;
407 
408  CLHEP::HepMatrix IC(2,2);
409  IC(1,1) = hit.localPositionError().xx();
410  IC(1,2) = hit.localPositionError().xy();
411  IC(2,2) = hit.localPositionError().yy();
412  IC(2,1) = IC(1,2);
413 
414  // Invert covariance matrix
415  int ierr = 0;
416  IC.invert(ierr);
417  if (ierr != 0) {
418  LogDebug("CSC") << "CSCSegment::fillChiSquared: failed to invert covariance matrix=\n" << IC << "\n";
419  }
420  chsq += du*du*IC(1,1) + 2.*du*dv*IC(1,2) + dv*dv*IC(2,2);
421  }
422  protoChi2 = chsq;
423 }
424 
425 
426 
427 /* Method compareProtoSegment
428  *
429  * For hit coming from the same layer of an existing hit within the proto segment
430  * test if achieve better chi^2 by using this hit than the other
431  *
432  */
434 
435  // Store old segment first
436  double old_protoChi2 = protoChi2;
437  LocalPoint old_protoIntercept = protoIntercept;
438  float old_protoSlope_u = protoSlope_u;
439  float old_protoSlope_v = protoSlope_v;
440  LocalVector old_protoDirection = protoDirection;
441  ChamberHitContainer old_protoSegment = protoSegment;
442 
443 
444  // Try adding the hit to existing segment, and remove old one existing in same layer
445  ChamberHitContainer::iterator it;
446  for ( it = protoSegment.begin(); it != protoSegment.end(); ) {
447  if ( (*it)->cscDetId().layer() == layer ) {
448  it = protoSegment.erase(it);
449  } else {
450  ++it;
451  }
452  }
453  bool ok = addHit(h, layer);
454 
455  if (ok) updateParameters();
456 
457  if ( (protoChi2 > old_protoChi2) || ( !ok ) ) {
458  protoChi2 = old_protoChi2;
459  protoIntercept = old_protoIntercept;
460  protoSlope_u = old_protoSlope_u;
461  protoSlope_v = old_protoSlope_v;
462  protoDirection = old_protoDirection;
463  protoSegment = old_protoSegment;
464  }
465 }
466 
468 
469  std::vector<const CSCRecHit2D*>::const_iterator it;
470  int nhits = protoSegment.size();
471  AlgebraicSymMatrix matrix(2*nhits, 0);
472  int row = 0;
473 
474  for (it = protoSegment.begin(); it != protoSegment.end(); ++it) {
475 
476  const CSCRecHit2D& hit = (**it);
477  ++row;
478  matrix(row, row) = hit.localPositionError().xx();
479  matrix(row, row+1) = hit.localPositionError().xy();
480  ++row;
481  matrix(row, row-1) = hit.localPositionError().xy();
482  matrix(row, row) = hit.localPositionError().yy();
483  }
484  int ierr;
485  matrix.invert(ierr);
486  return matrix;
487 }
488 
489 
490 CLHEP::HepMatrix CSCSegAlgoShowering::derivativeMatrix() const {
491 
492  ChamberHitContainer::const_iterator it;
493  int nhits = protoSegment.size();
494  CLHEP::HepMatrix matrix(2*nhits, 4);
495  int row = 0;
496 
497  for(it = protoSegment.begin(); it != protoSegment.end(); ++it) {
498 
499  const CSCRecHit2D& hit = (**it);
500  const CSCLayer* layer = theChamber->layer(hit.cscDetId().layer());
501  GlobalPoint gp = layer->toGlobal(hit.localPosition());
502  LocalPoint lp = theChamber->toLocal(gp);
503  float z = lp.z();
504  ++row;
505  matrix(row, 1) = 1.;
506  matrix(row, 3) = z;
507  ++row;
508  matrix(row, 2) = 1.;
509  matrix(row, 4) = z;
510  }
511  return matrix;
512 }
513 
514 /* calculateError
515  *
516  */
518 
521 
522  // (AT W A)^-1
523  // from http://www.phys.ufl.edu/~avery/fitting.html, part I
524  int ierr;
525  AlgebraicSymMatrix result = weights.similarityT(A);
526  result.invert(ierr);
527 
528  // blithely assuming the inverting never fails...
529  return result;
530 }
531 
533 
534  // The CSCSegment needs the error matrix re-arranged
535 
536  AlgebraicSymMatrix hold( a );
537 
538  // errors on slopes into upper left
539  a(1,1) = hold(3,3);
540  a(1,2) = hold(3,4);
541  a(2,1) = hold(4,3);
542  a(2,2) = hold(4,4);
543 
544  // errors on positions into lower right
545  a(3,3) = hold(1,1);
546  a(3,4) = hold(1,2);
547  a(4,3) = hold(2,1);
548  a(4,4) = hold(2,2);
549 
550  // off-diagonal elements remain unchanged
551 
552 }
553 
554 // Try to clean up segments by quickly looking at residuals
556 
557  // Only prune if have at least 5 hits
558  if ( protoSegment.size() < 5 ) return ;
559 
560 
561  // Now Study residuals
562 
563  float maxResidual = 0.;
564  float sumResidual = 0.;
565  int nHits = 0;
566  int badIndex = -1;
567  int j = 0;
568 
569 
570  ChamberHitContainer::const_iterator ih;
571 
572  for ( ih = protoSegment.begin(); ih != protoSegment.end(); ++ih ) {
573  const CSCRecHit2D& hit = (**ih);
574  const CSCLayer* layer = theChamber->layer(hit.cscDetId().layer());
575  GlobalPoint gp = layer->toGlobal(hit.localPosition());
576  LocalPoint lp = theChamber->toLocal(gp);
577 
578  double u = lp.x();
579  double v = lp.y();
580  double z = lp.z();
581 
582  double du = protoIntercept.x() + protoSlope_u * z - u;
583  double dv = protoIntercept.y() + protoSlope_v * z - v;
584 
585  float residual = sqrt(du*du + dv*dv);
586 
587  sumResidual += residual;
588  nHits++;
589  if ( residual > maxResidual ) {
590  maxResidual = residual;
591  badIndex = j;
592  }
593  j++;
594  }
595 
596  float corrAvgResidual = (sumResidual - maxResidual)/(nHits -1);
597 
598  // Keep all hits
599  if ( maxResidual/corrAvgResidual < maxRatioResidual ) return;
600 
601 
602  // Drop worse hit and recompute segment properties + fill
603 
604  ChamberHitContainer newProtoSegment;
605 
606  j = 0;
607  for ( ih = protoSegment.begin(); ih != protoSegment.end(); ++ih ) {
608  if ( j != badIndex ) newProtoSegment.push_back(*ih);
609  j++;
610  }
611 
612  protoSegment.clear();
613 
614  for ( ih = newProtoSegment.begin(); ih != newProtoSegment.end(); ++ih ) {
615  protoSegment.push_back(*ih);
616  }
617 
618  // Update segment parameters
620 
621 }
622 
623 
624 
625 
#define LogDebug(id)
T getParameter(std::string const &) const
int i
Definition: DBlmapReader.cc:9
float xx() const
Definition: LocalError.h:24
CSCSegment showerSeg(const CSCChamber *aChamber, ChamberHitContainer rechits)
CSCDetId cscDetId() const
Definition: CSCRecHit2D.h:52
void compareProtoSegment(const CSCRecHit2D *h, int layer)
AlgebraicSymMatrix calculateError(void) const
bool isHitNearSegment(const CSCRecHit2D *h) const
Utility functions.
virtual ~CSCSegAlgoShowering()
Destructor.
double_binary B
Definition: DDStreamer.cc:234
GlobalPoint toGlobal(const Local2DPoint &lp) const
Conversion to the global R.F. from the R.F. of the GeomDet.
Definition: GeomDet.h:47
Geom::Phi< T > phi() const
Definition: PV3DBase.h:68
T y() const
Definition: PV3DBase.h:62
LocalPoint toLocal(const GlobalPoint &gp) const
Conversion to the R.F. of the GeomDet.
Definition: GeomDet.h:62
int layer() const
Definition: CSCDetId.h:63
double double double z
Geom::Theta< T > theta() const
Definition: PV3DBase.h:74
bool addHit(const CSCRecHit2D *hit, int layer)
float xy() const
Definition: LocalError.h:25
T mag() const
Definition: PV3DBase.h:66
CLHEP::HepMatrix AlgebraicMatrix
LocalError localPositionError() const
Definition: CSCRecHit2D.h:51
double dPhi(double phi1, double phi2)
Definition: JetUtil.h:30
float yy() const
Definition: LocalError.h:26
string unit
Definition: csvLumiCalc.py:46
T sqrt(T t)
Definition: SSEVec.h:46
CSCSegAlgoShowering(const edm::ParameterSet &ps)
Constructor.
T z() const
Definition: PV3DBase.h:63
tuple result
Definition: query.py:137
CLHEP::HepMatrix derivativeMatrix(void) const
int j
Definition: DBlmapReader.cc:9
const CSCLayer * layer(CSCDetId id) const
Return the layer corresponding to the given id.
Definition: CSCChamber.cc:41
std::vector< const CSCRecHit2D * > ChamberHitContainer
#define M_PI
Definition: BFit3D.cc:3
The Signals That Services Can Subscribe To This is based on ActivityRegistry h
Helper function to determine trigger accepts.
Definition: Activities.doc:4
void flipErrors(AlgebraicSymMatrix &) const
AlgebraicSymMatrix weightMatrix(void) const
double a
Definition: hdecay.h:121
CLHEP::HepSymMatrix AlgebraicSymMatrix
Local3DPoint LocalPoint
Definition: LocalPoint.h:11
LocalPoint localPosition() const
Definition: CSCRecHit2D.h:50
x
Definition: VDTMath.h:216
T x() const
Definition: PV3DBase.h:61
mathSSE::Vec4< T > v
const CSCChamber * theChamber
ChamberHitContainer protoSegment