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