CMS 3D CMS Logo

CSCSegAlgoSK.cc
Go to the documentation of this file.
1 
6 #include "CSCSegAlgoSK.h"
7 #include "CSCSegFit.h"
10 
13 
14 #include <algorithm>
15 #include <cmath>
16 #include <iostream>
17 #include <string>
18 
20  : CSCSegmentAlgorithm(ps), myName("CSCSegAlgoSK"), sfit_(nullptr) {
21  debugInfo = ps.getUntrackedParameter<bool>("verboseInfo");
22 
23  dRPhiMax = ps.getParameter<double>("dRPhiMax");
24  dPhiMax = ps.getParameter<double>("dPhiMax");
25  dRPhiFineMax = ps.getParameter<double>("dRPhiFineMax");
26  dPhiFineMax = ps.getParameter<double>("dPhiFineMax");
27  chi2Max = ps.getParameter<double>("chi2Max");
28  wideSeg = ps.getParameter<double>("wideSeg");
29  minLayersApart = ps.getParameter<int>("minLayersApart");
30 
31  LogDebug("CSC") << myName << " has algorithm cuts set to: \n"
32  << "--------------------------------------------------------------------\n"
33  << "dRPhiMax = " << dRPhiMax << '\n'
34  << "dPhiMax = " << dPhiMax << '\n'
35  << "dRPhiFineMax = " << dRPhiFineMax << '\n'
36  << "dPhiFineMax = " << dPhiFineMax << '\n'
37  << "chi2Max = " << chi2Max << '\n'
38  << "wideSeg = " << wideSeg << '\n'
39  << "minLayersApart = " << minLayersApart << std::endl;
40 }
41 
42 std::vector<CSCSegment> CSCSegAlgoSK::run(const CSCChamber* aChamber, const ChamberHitContainer& rechits) {
43  theChamber = aChamber;
44  return buildSegments(rechits);
45 }
46 
47 std::vector<CSCSegment> CSCSegAlgoSK::buildSegments(const ChamberHitContainer& urechits) {
48  LogDebug("CSC") << "*********************************************";
49  LogDebug("CSC") << "Start segment building in the new chamber: " << theChamber->specs()->chamberTypeName();
50  LogDebug("CSC") << "*********************************************";
51 
52  ChamberHitContainer rechits = urechits;
53  LayerIndex layerIndex(rechits.size());
54 
55  for (unsigned int i = 0; i < rechits.size(); i++) {
56  layerIndex[i] = rechits[i]->cscDetId().layer();
57  }
58 
59  double z1 = theChamber->layer(1)->position().z();
60  double z6 = theChamber->layer(6)->position().z();
61 
62  if (z1 > 0.) {
63  if (z1 > z6) {
64  reverse(layerIndex.begin(), layerIndex.end());
65  reverse(rechits.begin(), rechits.end());
66  }
67  } else if (z1 < 0.) {
68  if (z1 < z6) {
69  reverse(layerIndex.begin(), layerIndex.end());
70  reverse(rechits.begin(), rechits.end());
71  }
72  }
73 
74  // if (debugInfo) dumpHits(rechits);
75 
76  if (rechits.size() < 2) {
77  LogDebug("CSC") << myName << ": " << rechits.size() << " hit(s) in chamber is not enough to build a segment.\n";
78  return std::vector<CSCSegment>();
79  }
80 
81  // We have at least 2 hits. We intend to try all possible pairs of hits to start
82  // segment building. 'All possible' means each hit lies on different layers in the chamber.
83  // BUT... once a hit has been assigned to a segment, we don't consider
84  // it again.
85 
86  // Choose first hit (as close to IP as possible) h1 and
87  // second hit (as far from IP as possible) h2
88  // To do this we iterate over hits in the chamber by layer - pick two layers.
89  // @@ Require the two layers are at least 3 layers apart. May need tuning?
90  // Then we iterate over hits within each of these layers and pick h1 and h2 from these.
91  // If they are 'close enough' we build an empty segment.
92  // Then try adding hits to this segment.
93 
94  // Initialize flags that a given hit has been allocated to a segment
95  BoolContainer used(rechits.size(), false);
96 
97  // Define buffer for segments we build
98  std::vector<CSCSegment> segments;
99 
100  // This is going to point to fits to hits, and its content will be used to create a CSCSegment
101  sfit_ = nullptr;
102 
104  ChamberHitContainerCIt ie = rechits.end();
105 
106  // Possibly allow 2 passes, second widening scale factor for cuts
107  windowScale = 1.; // scale factor for cuts
108 
109  int npass = (wideSeg > 1.) ? 2 : 1;
110 
111  for (int ipass = 0; ipass < npass; ++ipass) {
112  for (ChamberHitContainerCIt i1 = ib; i1 != ie; ++i1) {
113  bool segok = false;
114  if (used[i1 - ib])
115  continue;
116 
117  int layer1 = layerIndex[i1 - ib]; //(*i1)->cscDetId().layer();
118  const CSCRecHit2D* h1 = *i1;
119 
120  for (ChamberHitContainerCIt i2 = ie - 1; i2 != i1; --i2) {
121  if (used[i2 - ib])
122  continue;
123 
124  int layer2 = layerIndex[i2 - ib]; //(*i2)->cscDetId().layer();
125 
126  if (abs(layer2 - layer1) < minLayersApart)
127  break;
128  const CSCRecHit2D* h2 = *i2;
129 
130  if (areHitsCloseInLocalX(h1, h2) && areHitsCloseInGlobalPhi(h1, h2)) {
131  proto_segment.clear();
132 
133  const CSCLayer* l1 = theChamber->layer(layer1);
134  GlobalPoint gp1 = l1->toGlobal(h1->localPosition());
135  const CSCLayer* l2 = theChamber->layer(layer2);
136  GlobalPoint gp2 = l2->toGlobal(h2->localPosition());
137  LogDebug("CSC") << "start new segment from hits "
138  << "h1: " << gp1 << " - h2: " << gp2 << "\n";
139 
140  //@@ TRY ADDING A HIT - AND FIT
141  if (!addHit(h1, layer1)) {
142  LogDebug("CSC") << " failed to add hit h1\n";
143  continue;
144  }
145 
146  if (!addHit(h2, layer2)) {
147  LogDebug("CSC") << " failed to add hit h2\n";
148  continue;
149  }
150 
151  // Can only add hits if already have a segment
152  if (sfit_)
153  tryAddingHitsToSegment(rechits, used, layerIndex, i1, i2);
154 
155  // Check no. of hits on segment, and if enough flag them as used
156  // and store the segment
157  segok = isSegmentGood(rechits);
158  if (segok) {
159  flagHitsAsUsed(rechits, used);
160  // Copy the proto_segment and its properties inside a CSCSegment.
161  // Then fill the segment vector..
162 
163  if (proto_segment.empty()) {
164  LogDebug("CSC") << "No segment has been found !!!\n";
165  } else {
166  // Create an actual CSCSegment - retrieve all info from the fit
169  delete sfit_;
170  sfit_ = nullptr;
171  LogDebug("CSC") << "Found a segment !!!\n";
172  if (debugInfo)
173  dumpSegment(temp);
174  segments.push_back(temp);
175  }
176  }
177  } // h1 & h2 close
178 
179  if (segok)
180  break;
181  } // i2
182  } // i1
183 
184  if (segments.size() > 1)
185  break; // only change window if no segments found
186 
187  // Increase cut windows by factor of wideSeg
189 
190  } // ipass
191 
192  // Give the segments to the CSCChamber
193  return segments;
194 }
195 
197  const BoolContainer& used,
198  const LayerIndex& layerIndex,
200  const ChamberHitContainerCIt i2) {
201  // Iterate over the layers with hits in the chamber
202  // Skip the layers containing the segment endpoints
203  // Test each hit on the other layers to see if it is near the segment
204  // If it is, see whether there is already a hit on the segment from the same layer
205  // - if so, and there are more than 2 hits on the segment, copy the segment,
206  // replace the old hit with the new hit. If the new segment chi2 is better
207  // then replace the original segment with the new one (by swap)
208  // - if not, copy the segment, add the hit. If the new chi2/dof is still satisfactory
209  // then replace the original segment with the new one (by swap)
210 
212  ChamberHitContainerCIt ie = rechits.end();
213 
214  for (ChamberHitContainerCIt i = ib; i != ie; ++i) {
215  if (i == i1 || i == i2 || used[i - ib])
216  continue;
217 
218  int layer = layerIndex[i - ib];
219  const CSCRecHit2D* h = *i;
220  if (isHitNearSegment(h)) {
221  GlobalPoint gp1 = theChamber->layer(layer)->toGlobal(h->localPosition());
222  LogDebug("CSC") << " hit at global " << gp1 << " is near segment\n.";
223 
224  // Don't consider alternate hits on layers holding the two starting points
225  if (hasHitOnLayer(layer)) {
226  if (proto_segment.size() <= 2) {
227  LogDebug("CSC") << " " << proto_segment.size() << " hits on segment...skip hit on same layer.\n";
228  continue;
229  }
231  } else
233  } // h & seg close
234  } // i
235 }
236 
238  float deltaX = (h1->localPosition() - h2->localPosition()).x();
239  LogDebug("CSC") << " Hits at local x= " << h1->localPosition().x() << ", " << h2->localPosition().x()
240  << " have separation= " << deltaX;
241  return (fabs(deltaX) < (dRPhiMax * windowScale)) ? true : false; // +v
242 }
243 
245  const CSCLayer* l1 = theChamber->layer(h1->cscDetId().layer());
246  GlobalPoint gp1 = l1->toGlobal(h1->localPosition());
247  const CSCLayer* l2 = theChamber->layer(h2->cscDetId().layer());
248  GlobalPoint gp2 = l2->toGlobal(h2->localPosition());
249 
250  float h1p = gp1.phi();
251  float h2p = gp2.phi();
252  float dphi12 = h1p - h2p;
253 
254  // Into range [-pi, pi) (phi() returns values in this range)
255  if (dphi12 < -M_PI)
256  dphi12 += 2. * M_PI;
257  if (dphi12 > M_PI)
258  dphi12 -= 2. * M_PI;
259  LogDebug("CSC") << " Hits at global phi= " << h1p << ", " << h2p << " have separation= " << dphi12;
260  return (fabs(dphi12) < (dPhiMax * windowScale)) ? true : false; // +v
261 }
262 
264  // Is hit near segment?
265  // Requires deltaphi and rxy*deltaphi within ranges specified
266  // in parameter set, where rxy=sqrt(x**2+y**2) of hit itself.
267  // Note that to make intuitive cuts on delta(phi) one must work in
268  // phi range (-pi, +pi] not [0, 2pi)
269 
270  const CSCLayer* l1 = theChamber->layer(h->cscDetId().layer());
271  GlobalPoint hp = l1->toGlobal(h->localPosition());
272 
273  float hphi = hp.phi(); // in (-pi, +pi]
274  if (hphi < 0.)
275  hphi += 2. * M_PI; // into range [0, 2pi)
276  float sphi = phiAtZ(hp.z()); // in [0, 2*pi)
277  float phidif = sphi - hphi;
278  if (phidif < 0.)
279  phidif += 2. * M_PI; // into range [0, 2pi)
280  if (phidif > M_PI)
281  phidif -= 2. * M_PI; // into range (-pi, pi]
282 
283  float dRPhi = fabs(phidif) * hp.perp();
284  LogDebug("CSC") << " is hit at phi_h= " << hphi << " near segment phi_seg= " << sphi << "? is " << dRPhi << "<"
285  << dRPhiFineMax * windowScale << " ? "
286  << " and is |" << phidif << "|<" << dPhiFineMax * windowScale << " ?";
287 
288  return ((dRPhi < dRPhiFineMax * windowScale) && (fabs(phidif) < dPhiFineMax * windowScale)) ? true : false; // +v
289 }
290 
291 float CSCSegAlgoSK::phiAtZ(float z) const {
292  if (!sfit_) {
293  edm::LogVerbatim("CSCSegment") << "[CSCSegAlgoSK::phiAtZ] Segment fit undefined";
294  return 0.;
295  }
296 
297  // Returns a phi in [ 0, 2*pi )
298  const CSCLayer* l1 = theChamber->layer((*(proto_segment.begin()))->cscDetId().layer());
300  GlobalVector gv = l1->toGlobal(sfit_->localdir());
301 
302  LogTrace("CSCSegment") << "[CSCSegAlgoSK::phiAtZ] Global intercept = " << gp << ", direction = " << gv;
303 
304  float x = gp.x() + (gv.x() / gv.z()) * (z - gp.z());
305  float y = gp.y() + (gv.y() / gv.z()) * (z - gp.z());
306  float phi = atan2(y, x);
307  if (phi < 0.f)
308  phi += 2. * M_PI;
309 
310  return phi;
311 }
312 
314  // Dump positions of RecHit's in each CSCChamber
316  edm::LogInfo("CSCSegment") << "CSCChamber rechit dump.\n";
317  for (it = rechits.begin(); it != rechits.end(); it++) {
318  const CSCLayer* l1 = theChamber->layer((*it)->cscDetId().layer());
319  GlobalPoint gp1 = l1->toGlobal((*it)->localPosition());
320 
321  edm::LogInfo("CSCSegment") << "Global pos.: " << gp1 << ", phi: " << gp1.phi()
322  << ". Local position: " << (*it)->localPosition()
323  << ", phi: " << (*it)->localPosition().phi() << ". Layer: " << (*it)->cscDetId().layer()
324  << "\n";
325  }
326 }
327 
328 bool CSCSegAlgoSK::isSegmentGood(const ChamberHitContainer& rechitsInChamber) const {
329  // If the chamber has 20 hits or fewer, require at least 3 hits on segment
330  // If the chamber has >20 hits require at least 4 hits
331 
332  bool ok = false;
333 
334  unsigned int iadd = (rechitsInChamber.size() > 20) ? 1 : 0;
335 
336  if (windowScale > 1.)
337  iadd = 1;
338 
339  if (proto_segment.size() >= 3 + iadd)
340  ok = true;
341 
342  return ok;
343 }
344 
345 void CSCSegAlgoSK::flagHitsAsUsed(const ChamberHitContainer& rechitsInChamber, BoolContainer& used) const {
346  // Flag hits on segment as used
347  ChamberHitContainerCIt ib = rechitsInChamber.begin();
349 
350  for (hi = proto_segment.begin(); hi != proto_segment.end(); ++hi) {
351  for (iu = ib; iu != rechitsInChamber.end(); ++iu) {
352  if (*hi == *iu)
353  used[iu - ib] = true;
354  }
355  }
356 }
357 
358 bool CSCSegAlgoSK::addHit(const CSCRecHit2D* aHit, int layer) {
359  // Return true if hit was added successfully
360  // (and then parameters are updated).
361  // Return false if there is already a hit on the same layer, or insert failed.
362 
363  ChamberHitContainer::const_iterator it;
364 
365  for (it = proto_segment.begin(); it != proto_segment.end(); it++)
366  if (((*it)->cscDetId().layer() == layer) && (aHit != (*it)))
367  return false;
368 
369  proto_segment.push_back(aHit);
370 
371  // make a fit
373  return true;
374 }
375 
377  // Delete input CSCSegFit, create a new one and make the fit
378  delete sfit_;
380  sfit_->fit();
381 }
382 
384  // Is there is already a hit on this layer?
386 
387  for (it = proto_segment.begin(); it != proto_segment.end(); it++)
388  if ((*it)->cscDetId().layer() == layer)
389  return true;
390 
391  return false;
392 }
393 
395  // replace a hit from a layer
396  ChamberHitContainer::iterator it;
397  for (it = proto_segment.begin(); it != proto_segment.end();) {
398  if ((*it)->cscDetId().layer() == layer)
399  it = proto_segment.erase(it);
400  else
401  ++it;
402  }
403 
404  return addHit(h, layer);
405 }
406 
408  // Copy the input CSCSegFit
409  CSCSegFit* oldfit = new CSCSegFit(*sfit_);
410 
411  // May create a new fit
412  bool ok = replaceHit(h, layer);
413 
414  if (ok) {
415  LogDebug("CSCSegment") << " hit in same layer as a hit on segment; try replacing old one..."
416  << " chi2 new: " << sfit_->chi2() << " old: " << oldfit->chi2() << "\n";
417  }
418 
419  if ((sfit_->chi2() < oldfit->chi2()) && ok) {
420  LogDebug("CSC") << " segment with replaced hit is better.\n";
421  delete oldfit; // new fit is better
422  } else {
423  // keep original fit
424  delete sfit_; // now the new fit
425  sfit_ = oldfit; // reset to the original input fit
426  }
427 }
428 
430  // Copy input fit
431  CSCSegFit* oldfit = new CSCSegFit(*sfit_);
432 
433  // Creates a new fit
434  bool ok = addHit(h, layer);
435 
436  if (ok) {
437  LogDebug("CSCSegment") << " hit in new layer: added to segment, new chi2: " << sfit_->chi2() << "\n";
438  }
439 
440  // int ndf = 2*proto_segment.size() - 4;
441 
442  //@@ TEST ON ndof<=0 IS JUST TO ACCEPT nhits=2 CASE??
443  if (ok && ((sfit_->ndof() <= 0) || (sfit_->chi2() / sfit_->ndof() < chi2Max))) {
444  LogDebug("CSCSegment") << " segment with added hit is good.\n";
445  delete oldfit; // new fit is better
446  } else {
447  // reset to original fit
448  delete sfit_;
449  sfit_ = oldfit;
450  }
451 }
452 
453 void CSCSegAlgoSK::dumpSegment(const CSCSegment& seg) const {
454  edm::LogVerbatim("CSCSegment") << "CSCSegment in " << theChamber->id() << "\nlocal position = " << seg.localPosition()
455  << "\nerror = " << seg.localPositionError()
456  << "\nlocal direction = " << seg.localDirection()
457  << "\nerror =" << seg.localDirectionError() << "\ncovariance matrix"
458  << seg.parametersError() << "chi2/ndf = " << seg.chi2() << "/"
459  << seg.degreesOfFreedom() << "\n#rechits = " << seg.specificRecHits().size()
460  << "\ntime = " << seg.time();
461 }
Log< level::Info, true > LogVerbatim
std::vector< CSCSegment > run(const CSCChamber *aChamber, const ChamberHitContainer &rechits) override
Definition: CSCSegAlgoSK.cc:42
float dPhiFineMax
Definition: CSCSegAlgoSK.h:128
void fit(void)
Definition: CSCSegFit.cc:13
T getParameter(std::string const &) const
Definition: ParameterSet.h:303
const CSCLayer * layer(CSCDetId id) const
Return the layer corresponding to the given id.
Definition: CSCChamber.cc:30
double chi2(void) const
Definition: CSCSegFit.h:82
float time() const
Definition: CSCSegment.cc:144
LocalPoint localPosition() const override
Definition: CSCSegment.h:39
float phiAtZ(float z) const
ChamberHitContainer proto_segment
Definition: CSCSegAlgoSK.h:121
bool areHitsCloseInGlobalPhi(const CSCRecHit2D *h1, const CSCRecHit2D *h2) const
T z() const
Definition: PV3DBase.h:61
bool isHitNearSegment(const CSCRecHit2D *h) const
std::vector< const CSCRecHit2D * >::const_iterator ChamberHitContainerCIt
Definition: CSCSegAlgoSK.h:49
bool replaceHit(const CSCRecHit2D *h, int layer)
Geom::Phi< T > phi() const
Definition: PV3DBase.h:66
bool areHitsCloseInLocalX(const CSCRecHit2D *h1, const CSCRecHit2D *h2) const
Utility functions.
LocalPoint intercept() const
Definition: CSCSegFit.h:84
int ndof(void) const
Definition: CSCSegFit.h:83
CSCDetId cscDetId() const
Definition: CSCRecHit2D.h:58
int layer() const
Definition: CSCDetId.h:56
std::string chamberTypeName() const
bool addHit(const CSCRecHit2D *hit, int layer)
Utility functions.
float float float z
double chi2() const override
Chi2 of the segment fit.
Definition: CSCSegment.h:58
bool hasHitOnLayer(int layer) const
#define LogTrace(id)
constexpr std::array< uint8_t, layerIndexSize > layer
T getUntrackedParameter(std::string const &, T const &) const
LocalVector localDirection() const override
Local direction.
Definition: CSCSegment.h:42
float windowScale
Definition: CSCSegAlgoSK.h:124
CSCSegFit * sfit_
Definition: CSCSegAlgoSK.h:134
void increaseProtoSegment(const CSCRecHit2D *h, int layer)
Definition: EPCuts.h:4
void flagHitsAsUsed(const ChamberHitContainer &rechitsInChamber, BoolContainer &used) const
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
double f[11][100]
int degreesOfFreedom() const override
Degrees of freedom of the segment fit.
Definition: CSCSegment.h:62
void updateParameters(void)
CSCSegAlgoSK(const edm::ParameterSet &ps)
Constructor.
Definition: CSCSegAlgoSK.cc:19
GlobalPoint toGlobal(const Local2DPoint &lp) const
Conversion to the global R.F. from the R.F. of the GeomDet.
Definition: GeomDet.h:49
void dumpSegment(const CSCSegment &seg) const
#define M_PI
std::vector< CSCSegment > buildSegments(const ChamberHitContainer &rechits)
Definition: CSCSegAlgoSK.cc:47
LocalPoint localPosition() const override
Definition: CSCRecHit2D.h:56
LocalError localDirectionError() const override
Error on the local direction.
Definition: CSCSegment.cc:52
Log< level::Info, false > LogInfo
void dumpHits(const ChamberHitContainer &rechits) const
AlgebraicSymMatrix covarianceMatrix(void)
Definition: CSCSegFit.cc:352
T1 phi() const
Definition: Phi.h:78
bool isSegmentGood(const ChamberHitContainer &rechitsInChamber) const
AlgebraicSymMatrix parametersError() const override
Covariance matrix of parameters()
Definition: CSCSegment.h:49
const Surface::PositionType & position() const
The position (origin of the R.F.)
Definition: GeomDet.h:43
const std::string myName
Definition: CSCSegAlgoSK.h:122
std::vector< int > LayerIndex
Typedefs.
Definition: CSCSegAlgoSK.h:47
float dRPhiFineMax
Definition: CSCSegAlgoSK.h:127
const std::vector< CSCRecHit2D > & specificRecHits() const
Definition: CSCSegment.h:66
LocalVector localdir() const
Definition: CSCSegFit.h:85
std::vector< const CSCRecHit2D * > ChamberHitContainer
Definition: CSCSegAlgoSK.h:48
CSCSetOfHits hits(void) const
Definition: CSCSegFit.h:79
void tryAddingHitsToSegment(const ChamberHitContainer &rechitsInChamber, const BoolContainer &used, const LayerIndex &layerIndex, const ChamberHitContainerCIt i1, const ChamberHitContainerCIt i2)
LocalError localPositionError() const override
Definition: CSCSegment.cc:48
The Signals That Services Can Subscribe To This is based on ActivityRegistry h
Helper function to determine trigger accepts.
Definition: Activities.doc:4
const CSCChamberSpecs * specs() const
Definition: CSCChamber.h:39
std::deque< bool > BoolContainer
Definition: CSCSegAlgoSK.h:56
void compareProtoSegment(const CSCRecHit2D *h, int layer)
ib
Definition: cuy.py:661
const CSCChamber * theChamber
Definition: CSCSegAlgoSK.h:120
#define LogDebug(id)
CSCDetId id() const
Get the (concrete) DetId.
Definition: CSCChamber.h:34