CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
CSCSegAlgoTC.cc
Go to the documentation of this file.
1 
10 #include "CSCSegAlgoTC.h"
11 
14 
15 // For clhep Matrix::solve
18 
21 
23 
24 #include <algorithm>
25 #include <cmath>
26 #include <iostream>
27 #include <string>
28 
30  myName("CSCSegAlgoTC") {
31 
32  debugInfo = ps.getUntrackedParameter<bool>("verboseInfo");
33 
34  dRPhiMax = ps.getParameter<double>("dRPhiMax");
35  dPhiMax = ps.getParameter<double>("dPhiMax");
36  dRPhiFineMax = ps.getParameter<double>("dRPhiFineMax");
37  dPhiFineMax = ps.getParameter<double>("dPhiFineMax");
38  chi2Max = ps.getParameter<double>("chi2Max");
39  chi2ndfProbMin = ps.getParameter<double>("chi2ndfProbMin");
40  minLayersApart = ps.getParameter<int>("minLayersApart");
41  SegmentSorting = ps.getParameter<int>("SegmentSorting");
42 
43  LogDebug("CSC") << myName << " has algorithm cuts set to: \n"
44  << "--------------------------------------------------------------------\n"
45  << "dRPhiMax = " << dRPhiMax << '\n'
46  << "dPhiMax = " << dPhiMax << '\n'
47  << "dRPhiFineMax = " << dRPhiFineMax << '\n'
48  << "dPhiFineMax = " << dPhiFineMax << '\n'
49  << "chi2Max = " << chi2Max << '\n'
50  << "chi2ndfProbMin = " << chi2ndfProbMin << '\n'
51  << "minLayersApart = " << minLayersApart << '\n'
52  << "SegmentSorting = " << SegmentSorting << std::endl;
53 }
54 
55 std::vector<CSCSegment> CSCSegAlgoTC::run(const CSCChamber* aChamber, ChamberHitContainer rechits) {
56  theChamber = aChamber;
57  return buildSegments(rechits);
58 }
59 
61 
62  // Reimplementation of original algorithm of CSCSegmentizer, Mar-06
63 
64  LogDebug("CSC") << "*********************************************";
65  LogDebug("CSC") << "Start segment building in the new chamber: " << theChamber->specs()->chamberTypeName();
66  LogDebug("CSC") << "*********************************************";
67 
68  LayerIndex layerIndex(rechits.size());
69 
70  for(unsigned int i = 0; i < rechits.size(); i++) {
71 
72  layerIndex[i] = rechits[i]->cscDetId().layer();
73  }
74 
75  double z1 = theChamber->layer(1)->position().z();
76  double z6 = theChamber->layer(6)->position().z();
77 
78  if ( z1 > 0. ) {
79  if ( z1 > z6 ) {
80  reverse(layerIndex.begin(), layerIndex.end());
81  reverse(rechits.begin(), rechits.end());
82  }
83  }
84  else if ( z1 < 0. ) {
85  if ( z1 < z6 ) {
86  reverse(layerIndex.begin(), layerIndex.end());
87  reverse(rechits.begin(), rechits.end());
88  }
89  }
90 
91  if (debugInfo) {
92  // dump after sorting
93  dumpHits(rechits);
94  }
95 
96  if (rechits.size() < 2) {
97  LogDebug("CSC") << myName << ": " << rechits.size() <<
98  " hit(s) in chamber is not enough to build a segment.\n";
99  return std::vector<CSCSegment>();
100  }
101 
102  // We have at least 2 hits. We intend to try all possible pairs of hits to start
103  // segment building. 'All possible' means each hit lies on different layers in the chamber.
104  // For now we don't care whether a hit has already been allocated to another segment;
105  // we'll sort that out after building all possible segments.
106 
107  // Choose first hit (as close to IP as possible) h1 and
108  // second hit (as far from IP as possible) h2
109  // To do this we iterate over hits in the chamber by layer - pick two layers.
110  // @@ Require the two layers are at least 3 layers apart. May need tuning?
111  // Then we iterate over hits within each of these layers and pick h1 and h2 from these.
112  // If they are 'close enough' we build an empty segment.
113  // Then try adding hits to this segment.
114 
115  // Define buffer for segments we build (at the end we'll sort them somehow, and remove
116  // those which share hits with better-quality segments.
117 
118 
119  std::vector<CSCSegment> segments;
120 
121  ChamberHitContainerCIt ib = rechits.begin();
122  ChamberHitContainerCIt ie = rechits.end();
123 
124  for (ChamberHitContainerCIt i1 = ib; i1 != ie; ++i1) {
125 
126  int layer1 = layerIndex[i1-ib];
127  const CSCRecHit2D* h1 = *i1;
128 
129  for (ChamberHitContainerCIt i2 = ie-1; i2 != i1; --i2) {
130 
131  int layer2 = layerIndex[i2-ib];
132 
133  if (abs(layer2 - layer1) < minLayersApart)
134  break;
135 
136  const CSCRecHit2D* h2 = *i2;
137 
138  if (areHitsCloseInLocalX(h1, h2) && areHitsCloseInGlobalPhi(h1, h2)) {
139 
140  proto_segment.clear();
141 
142  const CSCLayer* l1 = theChamber->layer(h1->cscDetId().layer());
143  GlobalPoint gp1 = l1->toGlobal(h1->localPosition());
144  const CSCLayer* l2 = theChamber->layer(h2->cscDetId().layer());
145  GlobalPoint gp2 = l2->toGlobal(h2->localPosition());
146  LogDebug("CSC") << "start new segment from hits " << "h1: " << gp1 << " - h2: " << gp2 << "\n";
147 
148  if (!addHit(h1, layer1)) {
149  LogDebug("CSC") << " failed to add hit h1\n";
150  continue;
151  }
152 
153  if (!addHit(h2, layer2)) {
154  LogDebug("CSC") << " failed to add hit h2\n";
155  continue;
156  }
157 
158  tryAddingHitsToSegment(rechits, i1, i2); // changed seg
159 
160  // if a segment has been found push back it into the segment collection
161  if (proto_segment.empty()) {
162 
163  LogDebug("CSC") << "No segment has been found !!!\n";
164  }
165  else {
166 
167  // calculate error matrix
168  AlgebraicSymMatrix error_matrix = calculateError();
169 
170  // but reorder components to match what's required by TrackingRecHit interface
171  // i.e. slopes first, then positions
172  flipErrors( error_matrix );
173 
174  candidates.push_back(proto_segment);
175  origins.push_back(theOrigin);
176  directions.push_back(theDirection);
177  errors.push_back(error_matrix);
178  chi2s.push_back(theChi2);
179  LogDebug("CSC") << "Found a segment !!!\n";
180  }
181  }
182  }
183  }
184 
185  // We've built all possible segments. Now pick the best, non-overlapping subset.
186  pruneTheSegments(rechits);
187 
188  // Copy the selected proto segments into the CSCSegment vector
189  for(unsigned int i=0; i < candidates.size(); i++) {
190 
192  segments.push_back(temp);
193  }
194 
195  candidates.clear();
196  origins.clear();
197  directions.clear();
198  errors.clear();
199  chi2s.clear();
200 
201  // Give the segments to the CSCChamber
202  return segments;
203 }
204 
206  const ChamberHitContainerCIt i1, const ChamberHitContainerCIt i2) {
207 
208  // Iterate over the layers with hits in the chamber
209  // Skip the layers containing the segment endpoints
210  // Test each hit on the other layers to see if it is near the segment
211  // If it is, see whether there is already a hit on the segment from the same layer
212  // - if so, and there are more than 2 hits on the segment, copy the segment,
213  // replace the old hit with the new hit. If the new segment chi2 is better
214  // then replace the original segment with the new one (by swap)
215  // - if not, copy the segment, add the hit. If the new chi2/dof is still satisfactory
216  // then replace the original segment with the new one (by swap)
217 
218  ChamberHitContainerCIt ib = rechits.begin();
219  ChamberHitContainerCIt ie = rechits.end();
220 
221  for (ChamberHitContainerCIt i = ib; i != ie; ++i) {
222 
223  if ( i == i1 || i == i2 )
224  continue;
225 
226  int layer = (*i)->cscDetId().layer();
227  const CSCRecHit2D* h = *i;
228 
229  if (isHitNearSegment(h)) {
230 
231  const CSCLayer* l1 = theChamber->layer(h->cscDetId().layer());
232  GlobalPoint gp1 = l1->toGlobal(h->localPosition());
233  LogDebug("CSC") << " hit at global " << gp1 << " is near segment\n.";
234 
235  if (hasHitOnLayer(layer)) {
236  if (proto_segment.size() <= 2) {
237  LogDebug("CSC") << " " << proto_segment.size()
238  << " hits on segment...skip hit on same layer.\n";
239  continue;
240  }
241 
242  compareProtoSegment(h, layer);
243  }
244  else
245  increaseProtoSegment(h, layer);
246  } // h & seg close
247  } // i
248 }
249 
250 bool CSCSegAlgoTC::addHit(const CSCRecHit2D* aHit, int layer) {
251 
252  // Return true if hit was added successfully
253  // (and then parameters are updated).
254  // Return false if there is already a hit on the same layer, or insert failed.
255  bool ok = true;
256  ChamberHitContainer::const_iterator it;
257 
258  for(it = proto_segment.begin(); it != proto_segment.end(); it++)
259  if (((*it)->cscDetId().layer() == layer) && (aHit != *it))
260  return false;
261 
262  if (ok) {
263  proto_segment.push_back(aHit);
265  }
266  return ok;
267 }
268 
269 bool CSCSegAlgoTC::replaceHit(const CSCRecHit2D* h, int layer) {
270 
271  // replace a hit from a layer
272  ChamberHitContainer::iterator it;
273  for (it = proto_segment.begin(); it != proto_segment.end();) {
274  if ((*it)->cscDetId().layer() == layer)
275  it = proto_segment.erase(it);
276  else
277  ++it;
278  }
279 
280  return addHit(h, layer);
281 }
282 
284 
285  // Note that we need local position of a RecHit w.r.t. the CHAMBER
286  // and the RecHit itself only knows its local position w.r.t.
287  // the LAYER, so need to explicitly transform to global position.
288 
289  // no. of hits in the RecHitsOnSegment
290  // By construction this is the no. of layers with hitsna parte รจ da inserirsi tra le Contrade aperte ad accettare quello che
291 
292 
293  // since we allow just one hit per layer in a segment.
294 
295  int nh = proto_segment.size();
296 
297  // First hit added to a segment must always fail here
298  if (nh < 2)
299  return;
300 
301  if (nh == 2) {
302 
303  // Once we have two hits we can calculate a straight line
304  // (or rather, a straight line for each projection in xz and yz.)
305  ChamberHitContainer::const_iterator ih = proto_segment.begin();
306  int il1 = (*ih)->cscDetId().layer();
307  const CSCRecHit2D& h1 = (**ih);
308  ++ih;
309  int il2 = (*ih)->cscDetId().layer();
310  const CSCRecHit2D& h2 = (**ih);
311 
312  //@@ Skip if on same layer, but should be impossible
313  if (il1 == il2)
314  return;
315 
316  const CSCLayer* layer1 = theChamber->layer(il1);
317  const CSCLayer* layer2 = theChamber->layer(il2);
318 
319  GlobalPoint h1glopos = layer1->toGlobal(h1.localPosition());
320  GlobalPoint h2glopos = layer2->toGlobal(h2.localPosition());
321 
322  // localPosition is position of hit wrt layer (so local z = 0)
323  theOrigin = h1.localPosition();
324 
325  // We want hit wrt chamber (and local z will be != 0)
326  LocalPoint h1pos = theChamber->toLocal(h1glopos); // FIX !!
327  LocalPoint h2pos = theChamber->toLocal(h2glopos); // FIX !!
328 
329  float dz = h2pos.z()-h1pos.z();
330  uz = (h2pos.x()-h1pos.x())/dz ;
331  vz = (h2pos.y()-h1pos.y())/dz ;
332 
333  theChi2 = 0.;
334  }
335  else if (nh > 2) {
336 
337  // When we have more than two hits then we can fit projections to straight lines
338  fitSlopes();
339  fillChiSquared();
340  } // end of 'if' testing no. of hits
341 
343 }
344 
346 
347  // Update parameters of fit
348  // ptc 13-Aug-02: This does a linear least-squares fit
349  // to the hits associated with the segment, in the z projection.
350 
351  // In principle perhaps one could fit the strip and wire
352  // measurements (u, v respectively), to
353  // u = u0 + uz * z
354  // v = v0 + vz * z
355  // where u0, uz, v0, vz are the parameters resulting from the fit.
356  // But what is actually done is fit to the local x, y coordinates
357  // of the RecHits. However the strip measurement controls the precision
358  // of x, and the wire measurement controls that of y.
359  // Precision in local coordinate:
360  // u (strip, sigma~200um), v (wire, sigma~1cm)
361 
362  // I have verified that this code agrees with the formulation given
363  // on p246-247 of 'Data analysis techniques for high-energy physics
364  // experiments' by Bock, Grote, Notz & Regler, and that on p111-113
365  // of 'Statistics' by Barlow.
366 
367  // Formulate the matrix equation representing the least-squares fit
368  // We have a vector of measurements m, which is a 2n x 1 dim matrix
369  // The transpose mT is (u1, v1, u2, v2, ..., un, vn)
370  // where ui is the strip-associated measurement and vi is the
371  // wire-associated measurement for a given RecHit i.
372  // The fit is to
373  // u = u0 + uz * z
374  // v = v0 + vz * z
375  // where u0, uz, v0, vz are the parameters to be obtained from the fit.
376  // These are contained in a vector p which is a 4x1 dim matrix, and
377  // its transpose pT is (u0, v0, uz, vz). Note the ordering!
378  // The covariance matrix for each pair of measurements is 2 x 2 and
379  // the inverse of this is the error matrix E.
380  // The error matrix for the whole set of n measurements is a diagonal
381  // matrix with diagonal elements the individual 2 x 2 error matrices
382  // (because the inverse of a diagonal matrix is a diagonal matrix
383  // with each element the inverse of the original.)
384 
385  // The matrix 'matrix' in method 'CSCSegment::weightMatrix()' is this
386  // block-diagonal overall covariance matrix. It is inverted to the
387  // block-diagonal error matrix right before it is returned.
388 
389  // Use the matrix A defined by
390  // 1 0 z1 0
391  // 0 1 0 z1
392  // 1 0 z2 0
393  // 0 1 0 z2
394  // .. .. .. ..
395  // 1 0 zn 0
396  // 0 1 0 zn
397 
398  // The matrix A is returned by 'CSCSegment::derivativeMatrix()'.
399 
400  // Then the normal equations are encapsulated in the matrix equation
401  //
402  // (AT E A)p = (AT E)m
403  //
404  // where AT is the transpose of A.
405  // We'll call the combined matrix on the LHS, M, and that on the RHS, B:
406  // M p = B
407 
408  // We solve this for the parameter vector, p.
409  // The elements of M and B then involve sums over the hits
410 
411  // The 4 values in p are returned by 'CSCSegment::parameters()'
412  // in the order uz, vz, u0, v0.
413  // The error matrix of the parameters is obtained by
414  // (AT E A)^-1
415  // calculated in 'CSCSegment::parametersErrors()'.
416 
417  // NOTE 1
418  // It does the #hits = 2 case separately.
419  // (I hope they're not on the same layer! They should not be, by construction.)
420 
421  // NOTE 2
422  // We need local position of a RecHit w.r.t. the CHAMBER
423  // and the RecHit itself only knows its local position w.r.t.
424  // the LAYER, so we must explicitly transform global position.
425 
426  CLHEP::HepMatrix M(4,4,0);
427  CLHEP::HepVector B(4,0);
428 
429  ChamberHitContainer::const_iterator ih = proto_segment.begin();
430 
431  for (ih = proto_segment.begin(); ih != proto_segment.end(); ++ih) {
432 
433  const CSCRecHit2D& hit = (**ih);
434  const CSCLayer* layer = theChamber->layer(hit.cscDetId().layer());
435  GlobalPoint gp = layer->toGlobal(hit.localPosition());
436  LocalPoint lp = theChamber->toLocal(gp); // FIX !!
437 
438  // ptc: Local position of hit w.r.t. chamber
439  double u = lp.x();
440  double v = lp.y();
441  double z = lp.z();
442 
443  // ptc: Covariance matrix of local errors MUST BE CHECKED IF COMAPTIBLE
444  CLHEP::HepMatrix IC(2,2);
445  IC(1,1) = hit.localPositionError().xx();
446  IC(1,2) = hit.localPositionError().xy();
447  IC(2,1) = IC(1,2); // since Cov is symmetric
448  IC(2,2) = hit.localPositionError().yy();
449 
450  // ptc: Invert covariance matrix (and trap if it fails!)
451  int ierr = 0;
452  IC.invert(ierr); // inverts in place
453  if (ierr != 0) {
454  LogDebug("CSC") << "CSCSegment::fitSlopes: failed to invert covariance matrix=\n" << IC << "\n";
455 
456  // @@ NOW WHAT TO DO? Exception? Return? Ignore?
457  }
458 
459  // ptc: Note that IC is no longer Cov but Cov^-1
460  M(1,1) += IC(1,1);
461  M(1,2) += IC(1,2);
462  M(1,3) += IC(1,1) * z;
463  M(1,4) += IC(1,2) * z;
464  B(1) += u * IC(1,1) + v * IC(1,2);
465 
466  M(2,1) += IC(2,1);
467  M(2,2) += IC(2,2);
468  M(2,3) += IC(2,1) * z;
469  M(2,4) += IC(2,2) * z;
470  B(2) += u * IC(2,1) + v * IC(2,2);
471 
472  M(3,1) += IC(1,1) * z;
473  M(3,2) += IC(1,2) * z;
474  M(3,3) += IC(1,1) * z * z;
475  M(3,4) += IC(1,2) * z * z;
476  B(3) += ( u * IC(1,1) + v * IC(1,2) ) * z;
477 
478  M(4,1) += IC(2,1) * z;
479  M(4,2) += IC(2,2) * z;
480  M(4,3) += IC(2,1) * z * z;
481  M(4,4) += IC(2,2) * z * z;
482  B(4) += ( u * IC(2,1) + v * IC(2,2) ) * z;
483  }
484 
485  // Solve the matrix equation using CLHEP's 'solve'
486  //@@ ptc: CAN solve FAIL?? UNCLEAR FROM (LACK OF) CLHEP DOC
487  CLHEP::HepVector p = solve(M, B);
488 
489  // Update member variables uz, vz, theOrigin
490  theOrigin = LocalPoint(p(1), p(2), 0.);
491  uz = p(3);
492  vz = p(4);
493 }
494 
496 
497  // The chi-squared is (m-Ap)T E (m-Ap)
498  // where T denotes transpose.
499  // This collapses to a simple sum over contributions from each
500  // pair of measurements.
501  float u0 = theOrigin.x();
502  float v0 = theOrigin.y();
503  double chsq = 0.;
504 
505  ChamberHitContainer::const_iterator ih;
506  for (ih = proto_segment.begin(); ih != proto_segment.end(); ++ih) {
507 
508  const CSCRecHit2D& hit = (**ih);
509  const CSCLayer* layer = theChamber->layer(hit.cscDetId().layer());
510  GlobalPoint gp = layer->toGlobal(hit.localPosition());
511  LocalPoint lp = theChamber->toLocal(gp); // FIX !!
512 
513  double hu = lp.x();
514  double hv = lp.y();
515  double hz = lp.z();
516 
517  double du = u0 + uz * hz - hu;
518  double dv = v0 + vz * hz - hv;
519 
520  CLHEP::HepMatrix IC(2,2);
521  IC(1,1) = hit.localPositionError().xx();
522  IC(1,2) = hit.localPositionError().xy();
523  IC(2,1) = IC(1,2);
524  IC(2,2) = hit.localPositionError().yy();
525 
526  // Invert covariance matrix
527  int ierr = 0;
528  IC.invert(ierr);
529  if (ierr != 0) {
530  LogDebug("CSC") << "CSCSegment::fillChiSquared: failed to invert covariance matrix=\n" << IC << "\n";
531 
532  // @@ NOW WHAT TO DO? Exception? Return? Ignore?
533  }
534 
535  chsq += du*du*IC(1,1) + 2.*du*dv*IC(1,2) + dv*dv*IC(2,2);
536  }
537  theChi2 = chsq;
538 }
539 
541 
542  // Always enforce direction of segment to point from IP outwards
543  // (Incorrect for particles not coming from IP, of course.)
544 
545  double dxdz = uz;
546  double dydz = vz;
547  double dz = 1./sqrt(1. + dxdz*dxdz + dydz*dydz);
548  double dx = dz*dxdz;
549  double dy = dz*dydz;
550  LocalVector localDir(dx,dy,dz);
551 
552  // localDir may need sign flip to ensure it points outward from IP
553  // ptc: Examine its direction and origin in global z: to point outward
554  // the localDir should always have same sign as global z...
555 
556  double globalZpos = ( theChamber->toGlobal( theOrigin ) ).z();
557  double globalZdir = ( theChamber->toGlobal( localDir ) ).z();
558  double directionSign = globalZpos * globalZdir;
559 
560  theDirection = (directionSign * localDir).unit();
561 }
562 
563 float CSCSegAlgoTC::phiAtZ(float z) const {
564 
565  // Returns a phi in [ 0, 2*pi )
566  const CSCLayer* l1 = theChamber->layer(1);
567  GlobalPoint gp = l1->toGlobal(theOrigin);
569 
570  float x = gp.x() + (gv.x()/gv.z())*(z - gp.z());
571  float y = gp.y() + (gv.y()/gv.z())*(z - gp.z());
572  float phi = atan2(y, x);
573  if (phi < 0.f)
574  phi += 2. * M_PI;
575 
576  return phi ;
577 }
578 
580 
581  // compare the chi2 of two segments
582  double oldChi2 = theChi2;
583  LocalPoint oldOrigin = theOrigin;
584  LocalVector oldDirection = theDirection;
585  ChamberHitContainer oldSegment = proto_segment;
586 
587  bool ok = replaceHit(h, layer);
588 
589  if (ok) {
590  LogDebug("CSC") << " hit in same layer as a hit on segment; try replacing old one..."
591  << " chi2 new: " << theChi2 << " old: " << oldChi2 << "\n";
592  }
593 
594  if ((theChi2 < oldChi2) && (ok)) {
595  LogDebug("CSC") << " segment with replaced hit is better.\n";
596  }
597  else {
598  proto_segment = oldSegment;
599  theChi2 = oldChi2;
600  theOrigin = oldOrigin;
601  theDirection = oldDirection;
602  }
603 }
604 
606 
607  double oldChi2 = theChi2;
608  LocalPoint oldOrigin = theOrigin;
609  LocalVector oldDirection = theDirection;
610  ChamberHitContainer oldSegment = proto_segment;
611 
612  bool ok = addHit(h, layer);
613 
614  if (ok) {
615  LogDebug("CSC") << " hit in new layer: added to segment, new chi2: "
616  << theChi2 << "\n";
617  }
618 
619  int ndf = 2*proto_segment.size() - 4;
620 
621  if (ok && ((ndf <= 0) || (theChi2/ndf < chi2Max))) {
622  LogDebug("CSC") << " segment with added hit is good.\n" ;
623  }
624  else {
625  proto_segment = oldSegment;
626  theChi2 = oldChi2;
627  theOrigin = oldOrigin;
628  theDirection = oldDirection;
629  }
630 }
631 
633  float h1x = h1->localPosition().x();
634  float h2x = h2->localPosition().x();
635  float deltaX = (h1->localPosition()-h2->localPosition()).x();
636  LogDebug("CSC") << " Hits at local x= " << h1x << ", "
637  << h2x << " have separation= " << deltaX;
638  return (fabs(deltaX) < (dRPhiMax))? true:false; // +v
639 }
640 
642 
643  const CSCLayer* l1 = theChamber->layer(h1->cscDetId().layer());
644  GlobalPoint gp1 = l1->toGlobal(h1->localPosition());
645  const CSCLayer* l2 = theChamber->layer(h2->cscDetId().layer());
646  GlobalPoint gp2 = l2->toGlobal(h2->localPosition());
647 
648  float h1p = gp1.phi();
649  float h2p = gp2.phi();
650  float dphi12 = h1p - h2p;
651 
652  // Into range [-pi, pi) (phi() returns values in this range)
653  if (dphi12 < -M_PI)
654  dphi12 += 2.*M_PI;
655  if (dphi12 > M_PI)
656  dphi12 -= 2.*M_PI;
657  LogDebug("CSC") << " Hits at global phi= " << h1p << ", "
658  << h2p << " have separation= " << dphi12;
659  return (fabs(dphi12) < dPhiMax)? true:false; // +v
660 }
661 
663 
664  // Is hit near segment?
665  // Requires deltaphi and rxy*deltaphi within ranges specified
666  // in orcarc, or by default, where rxy=sqrt(x**2+y**2) of hit itself.
667  // Note that to make intuitive cuts on delta(phi) one must work in
668  // phi range (-pi, +pi] not [0, 2pi
669 
670  const CSCLayer* l1 = theChamber->layer(h->cscDetId().layer());
671  GlobalPoint hp = l1->toGlobal(h->localPosition());
672 
673  float hphi = hp.phi(); // in (-pi, +pi]
674  if (hphi < 0.)
675  hphi += 2.*M_PI; // into range [0, 2pi)
676  float sphi = phiAtZ(hp.z()); // in [0, 2*pi)
677  float phidif = sphi-hphi;
678  if (phidif < 0.)
679  phidif += 2.*M_PI; // into range [0, 2pi)
680  if (phidif > M_PI)
681  phidif -= 2.*M_PI; // into range (-pi, pi]
682 
683  float dRPhi = fabs(phidif)*hp.perp();
684  LogDebug("CSC") << " is hit at phi_h= " << hphi << " near segment phi_seg= " << sphi
685  << "? is " << dRPhi << "<" << dRPhiFineMax << " ? "
686  << " and is |" << phidif << "|<" << dPhiFineMax << " ?";
687 
688  return ((dRPhi < dRPhiFineMax) &&
689  (fabs(phidif) < dPhiFineMax))? true:false; // +v
690 }
691 
692 bool CSCSegAlgoTC::hasHitOnLayer(int layer) const {
693 
694  // Is there is already a hit on this layer?
696 
697  for(it = proto_segment.begin(); it != proto_segment.end(); it++)
698  if ((*it)->cscDetId().layer() == layer)
699  return true;
700 
701  return false;
702 }
703 
705 
706  // Dump positions of RecHit's in each CSCChamber
708 
709  for(it=rechits.begin(); it!=rechits.end(); it++) {
710 
711  const CSCLayer* l1 = theChamber->layer((*it)->cscDetId().layer());
712  GlobalPoint gp1 = l1->toGlobal((*it)->localPosition());
713 
714  LogDebug("CSC") << "Global pos.: " << gp1 << ", phi: " << gp1.phi() << ". Local position: "
715  << (*it)->localPosition() << ", phi: "
716  << (*it)->localPosition().phi() << ". Layer: "
717  << (*it)->cscDetId().layer() << "\n";
718  }
719 }
720 
721 
722 bool CSCSegAlgoTC::isSegmentGood(std::vector<ChamberHitContainer>::iterator seg, std::vector<double>::iterator chi2,
723  const ChamberHitContainer& rechitsInChamber, BoolContainer& used) const {
724 
725  // Apply any selection cuts to segment
726 
727  // 1) Require a minimum no. of hits
728  // (@@ THESE VALUES SHOULD BECOME PARAMETERS?)
729 
730  // 2) Ensure no hits on segment are already assigned to another segment
731  // (typically of higher quality)
732 
733  unsigned int iadd = (rechitsInChamber.size() > 20 )? 1 : 0;
734 
735  if (seg->size() < 3 + iadd)
736  return false;
737 
738  // Additional part of alternative segment selection scheme: reject
739  // segments with a chi2 probability of less than chi2ndfProbMin. Relies on list
740  // being sorted with "SegmentSorting == 2", that is first by nrechits and then
741  // by chi2prob in subgroups of same nr of rechits.
742 
743  if( SegmentSorting == 2 ){
744  if( (*chi2) != 0 && ((2*seg->size())-4) >0 ) {
745  if ( ChiSquaredProbability((*chi2),(double)(2*seg->size()-4)) < chi2ndfProbMin ) {
746  return false;
747  }
748  }
749  if((*chi2) == 0 ) return false;
750  }
751 
752 
753  for(unsigned int ish = 0; ish < seg->size(); ++ish) {
754 
755  ChamberHitContainerCIt ib = rechitsInChamber.begin();
756 
757  for(ChamberHitContainerCIt ic = ib; ic != rechitsInChamber.end(); ++ic) {
758 
759  if(((*seg)[ish] == (*ic)) && used[ic-ib])
760  return false;
761  }
762  }
763 
764  return true;
765 }
766 
767 void CSCSegAlgoTC::flagHitsAsUsed(std::vector<ChamberHitContainer>::iterator seg, const ChamberHitContainer& rechitsInChamber,
768  BoolContainer& used) const {
769 
770  // Flag hits on segment as used
771 
772  ChamberHitContainerCIt ib = rechitsInChamber.begin();
773 
774  for(unsigned int ish = 0; ish < seg->size(); ish++) {
775 
776  for(ChamberHitContainerCIt iu = ib; iu != rechitsInChamber.end(); ++iu)
777  if((*seg)[ish] == (*iu))
778  used[iu-ib] = true;
779  }
780 }
781 
783 
784  // Sort the segment store according to segment 'quality' (chi2/#hits ?) and
785  // remove any segments which contain hits assigned to higher-quality segments.
786 
787  if (candidates.empty())
788  return;
789 
790  // Initialize flags that a given hit has been allocated to a segment
791  BoolContainer used(rechitsInChamber.size(), false);
792 
793  // Sort by chi2/#hits
794  segmentSort();
795 
796  // Select best quality segments, requiring hits are assigned to just one segment
797  // Because I want to erase the bad segments, the iterator must be incremented
798  // inside the loop, and only when the erase is not called
799 
800  std::vector<ChamberHitContainer>::iterator is;
801  std::vector<double>::iterator ichi = chi2s.begin();
802  std::vector<AlgebraicSymMatrix>::iterator iErr = errors.begin();
803  std::vector<LocalPoint>::iterator iOrig = origins.begin();
804  std::vector<LocalVector>::iterator iDir = directions.begin();
805 
806  for (is = candidates.begin(); is != candidates.end(); ) {
807 
808  bool goodSegment = isSegmentGood(is, ichi, rechitsInChamber, used);
809 
810  if (goodSegment) {
811  LogDebug("CSC") << "Accepting segment: ";
812 
813  flagHitsAsUsed(is, rechitsInChamber, used);
814  ++is;
815  ++ichi;
816  ++iErr;
817  ++iOrig;
818  ++iDir;
819  }
820  else {
821  LogDebug("CSC") << "Rejecting segment: ";
822  is = candidates.erase(is);
823  ichi = chi2s.erase(ichi);
824  iErr = errors.erase(iErr);
825  iOrig = origins.erase(iOrig);
826  iDir = directions.erase(iDir);
827  }
828  }
829 }
830 
832 
833  // The segment collection is sorted according chi2/#hits
834 
835  for(unsigned int i=0; i<candidates.size()-1; i++) {
836  for(unsigned int j=i+1; j<candidates.size(); j++) {
837 
840  if (i == j)
841  continue;
842 
843  int n1 = candidates[i].size();
844  int n2 = candidates[j].size();
845 
846  if( SegmentSorting == 2 ){ // Sort criterion: first sort by Nr of rechits, then in groups of rechits by chi2prob:
847  if ( n2 > n1 ) { // sort by nr of rechits
849  candidates[j] = candidates[i];
850  candidates[i] = temp;
851 
852  double temp1 = chi2s[j];
853  chi2s[j] = chi2s[i];
854  chi2s[i] = temp1;
855 
856  AlgebraicSymMatrix temp2 = errors[j];
857  errors[j] = errors[i];
858  errors[i] = temp2;
859 
860  LocalPoint temp3 = origins[j];
861  origins[j] = origins[i];
862  origins[i] = temp3;
863 
864  LocalVector temp4 = directions[j];
865  directions[j] = directions[i];
866  directions[i] = temp4;
867  }
868  // sort by chi2 probability in subgroups with equal nr of rechits
869  if(chi2s[i] != 0. && 2*n2-4 > 0 ) {
870  if( n2 == n1 && (ChiSquaredProbability( chi2s[i],(double)(2*n1-4)) < ChiSquaredProbability(chi2s[j],(double)(2*n2-4))) ){
872  candidates[j] = candidates[i];
873  candidates[i] = temp;
874 
875  double temp1 = chi2s[j];
876  chi2s[j] = chi2s[i];
877  chi2s[i] = temp1;
878 
879  AlgebraicSymMatrix temp2 = errors[j];
880  errors[j] = errors[i];
881  errors[i] = temp2;
882 
883  LocalPoint temp3 = origins[j];
884  origins[j] = origins[i];
885  origins[i] = temp3;
886 
887  LocalVector temp4 = directions[j];
888  directions[j] = directions[i];
889  directions[i] = temp4;
890  }
891  }
892  }
893  else if( SegmentSorting == 1 ){
894  if ((chi2s[i]/n1) > (chi2s[j]/n2)) {
895 
897  candidates[j] = candidates[i];
898  candidates[i] = temp;
899 
900  double temp1 = chi2s[j];
901  chi2s[j] = chi2s[i];
902  chi2s[i] = temp1;
903 
904  AlgebraicSymMatrix temp2 = errors[j];
905  errors[j] = errors[i];
906  errors[i] = temp2;
907 
908  LocalPoint temp3 = origins[j];
909  origins[j] = origins[i];
910  origins[i] = temp3;
911 
912  LocalVector temp4 = directions[j];
913  directions[j] = directions[i];
914  directions[i] = temp4;
915  }
916  }
917  else{
918  LogDebug("CSC") << "No valid segment sorting specified - BAD !!!\n";
919  }
920  }
921  }
922 }
923 
925 
928 
929  // (AT W A)^-1
930  // from http://www.phys.ufl.edu/~avery/fitting.html, part I
931  int ierr;
932  AlgebraicSymMatrix result = weights.similarityT(A);
933  result.invert(ierr);
934 
935  // blithely assuming the inverting never fails...
936  return result;
937 }
938 
939 CLHEP::HepMatrix CSCSegAlgoTC::derivativeMatrix() const {
940 
941  ChamberHitContainer::const_iterator it;
942  int nhits = proto_segment.size();
943  CLHEP::HepMatrix matrix(2*nhits, 4);
944  int row = 0;
945 
946  for(it = proto_segment.begin(); it != proto_segment.end(); ++it) {
947 
948  const CSCRecHit2D& hit = (**it);
949  const CSCLayer* layer = theChamber->layer(hit.cscDetId().layer());
950  GlobalPoint gp = layer->toGlobal(hit.localPosition());
951  LocalPoint lp = theChamber->toLocal(gp); // FIX
952  float z = lp.z();
953  ++row;
954  matrix(row, 1) = 1.;
955  matrix(row, 3) = z;
956  ++row;
957  matrix(row, 2) = 1.;
958  matrix(row, 4) = z;
959  }
960  return matrix;
961 }
962 
963 
965 
966  std::vector<const CSCRecHit2D*>::const_iterator it;
967  int nhits = proto_segment.size();
968  AlgebraicSymMatrix matrix(2*nhits, 0);
969  int row = 0;
970 
971  for (it = proto_segment.begin(); it != proto_segment.end(); ++it) {
972 
973  const CSCRecHit2D& hit = (**it);
974  ++row;
975  matrix(row, row) = hit.localPositionError().xx();
976  matrix(row, row+1) = hit.localPositionError().xy();
977  ++row;
978  matrix(row, row-1) = hit.localPositionError().xy();
979  matrix(row, row) = hit.localPositionError().yy();
980  }
981  int ierr;
982  matrix.invert(ierr);
983  return matrix;
984 }
985 
987 
988  // The CSCSegment needs the error matrix re-arranged
989 
990  AlgebraicSymMatrix hold( a );
991 
992  // errors on slopes into upper left
993  a(1,1) = hold(3,3);
994  a(1,2) = hold(3,4);
995  a(2,1) = hold(4,3);
996  a(2,2) = hold(4,4);
997 
998  // errors on positions into lower right
999  a(3,3) = hold(1,1);
1000  a(3,4) = hold(1,2);
1001  a(4,3) = hold(2,1);
1002  a(4,4) = hold(2,2);
1003 
1004  // off-diagonal elements remain unchanged
1005 
1006 }
1007 
#define LogDebug(id)
T getParameter(std::string const &) const
T getUntrackedParameter(std::string const &, T const &) const
void fillLocalDirection()
int i
Definition: DBlmapReader.cc:9
float xx() const
Definition: LocalError.h:24
CSCDetId cscDetId() const
Definition: CSCRecHit2D.h:52
T perp() const
Definition: PV3DBase.h:71
const std::string myName
Definition: CSCSegAlgoTC.h:212
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
std::vector< AlgebraicSymMatrix > errors
Definition: CSCSegAlgoTC.h:161
#define abs(x)
Definition: mlp_lapack.h:159
LocalPoint toLocal(const GlobalPoint &gp) const
Conversion to the R.F. of the GeomDet.
Definition: GeomDet.h:62
void compareProtoSegment(const CSCRecHit2D *h, int layer)
AlgebraicSymMatrix weightMatrix() const
std::deque< bool > BoolContainer
Definition: CSCSegAlgoTC.h:59
int layer() const
Definition: CSCDetId.h:63
float phiAtZ(float z) const
AlgebraicSymMatrix calculateError() const
double double double z
tuple s2
Definition: indexGen.py:106
bool areHitsCloseInLocalX(const CSCRecHit2D *h1, const CSCRecHit2D *h2) const
bool isHitNearSegment(const CSCRecHit2D *h) const
std::string chamberTypeName() const
void updateParameters()
float xy() const
Definition: LocalError.h:25
void dumpHits(const ChamberHitContainer &rechits) const
const Surface::PositionType & position() const
The position (origin of the R.F.)
Definition: GeomDet.h:41
const CSCChamberSpecs * specs() const
Definition: CSCChamber.h:42
CLHEP::HepMatrix AlgebraicMatrix
std::vector< double > chi2s
Definition: CSCSegAlgoTC.h:162
LocalError localPositionError() const
Definition: CSCRecHit2D.h:51
float yy() const
Definition: LocalError.h:26
string unit
Definition: csvLumiCalc.py:46
T sqrt(T t)
Definition: SSEVec.h:46
LocalVector theDirection
Definition: CSCSegAlgoTC.h:167
T z() const
Definition: PV3DBase.h:63
tuple result
Definition: query.py:137
void fillChiSquared()
int j
Definition: DBlmapReader.cc:9
const CSCLayer * layer(CSCDetId id) const
Return the layer corresponding to the given id.
Definition: CSCChamber.cc:41
void flagHitsAsUsed(std::vector< ChamberHitContainer >::iterator is, const ChamberHitContainer &rechitsInChamber, BoolContainer &used) const
float dRPhiFineMax
Definition: CSCSegAlgoTC.h:182
double f[11][100]
float ChiSquaredProbability(double chiSquared, double nrDOF)
bool isSegmentGood(std::vector< ChamberHitContainer >::iterator is, std::vector< double >::iterator ichi, const ChamberHitContainer &rechitsInChamber, BoolContainer &used) const
bool areHitsCloseInGlobalPhi(const CSCRecHit2D *h1, const CSCRecHit2D *h2) const
bool addHit(const CSCRecHit2D *aHit, int layer)
Utility functions.
float chi2ndfProbMin
Definition: CSCSegAlgoTC.h:177
void segmentSort()
double theChi2
Definition: CSCSegAlgoTC.h:165
const CSCChamber * theChamber
Member variables.
Definition: CSCSegAlgoTC.h:157
std::vector< CSCSegment > buildSegments(ChamberHitContainer rechits)
Definition: CSCSegAlgoTC.cc:60
#define M_PI
Definition: BFit3D.cc:3
ChamberHitContainer proto_segment
Definition: CSCSegAlgoTC.h:164
The Signals That Services Can Subscribe To This is based on ActivityRegistry h
Helper function to determine trigger accepts.
Definition: Activities.doc:4
std::vector< const CSCRecHit2D * > ChamberHitContainer
Definition: CSCSegAlgoTC.h:51
std::vector< LocalPoint > origins
Definition: CSCSegAlgoTC.h:159
void tryAddingHitsToSegment(const ChamberHitContainer &rechits, const ChamberHitContainerCIt i1, const ChamberHitContainerCIt i2)
void fitSlopes()
bool hasHitOnLayer(int layer) const
CLHEP::HepMatrix derivativeMatrix() const
std::vector< CSCSegment > run(const CSCChamber *aChamber, ChamberHitContainer rechits)
Definition: CSCSegAlgoTC.cc:55
LocalPoint theOrigin
Definition: CSCSegAlgoTC.h:166
double a
Definition: hdecay.h:121
CLHEP::HepSymMatrix AlgebraicSymMatrix
Local3DPoint LocalPoint
Definition: LocalPoint.h:11
std::vector< int > LayerIndex
Typedefs.
Definition: CSCSegAlgoTC.h:50
std::vector< ChamberHitContainer > candidates
Definition: CSCSegAlgoTC.h:158
Definition: DDAxes.h:10
LocalPoint localPosition() const
Definition: CSCRecHit2D.h:50
T x() const
Definition: PV3DBase.h:61
ChamberHitContainer::const_iterator ChamberHitContainerCIt
Definition: CSCSegAlgoTC.h:52
mathSSE::Vec4< T > v
void increaseProtoSegment(const CSCRecHit2D *h, int layer)
void pruneTheSegments(const ChamberHitContainer &rechitsInChamber)
void flipErrors(AlgebraicSymMatrix &) const
bool replaceHit(const CSCRecHit2D *h, int layer)
CSCSegAlgoTC(const edm::ParameterSet &ps)
Constructor.
Definition: CSCSegAlgoTC.cc:29
float dPhiFineMax
Definition: CSCSegAlgoTC.h:187
Definition: DDAxes.h:10