CMS 3D CMS Logo

CSCSegAlgoST.cc
Go to the documentation of this file.
1 
12 #include "CSCSegAlgoST.h"
13 #include "CSCCondSegFit.h"
14 #include "CSCSegAlgoShowering.h"
15 
17 
19 
21 
23 
24 #include <algorithm>
25 #include <cmath>
26 #include <iostream>
27 #include <string>
28 
29 /* constructor
30  *
31  */
33  : CSCSegmentAlgorithm(ps), myName_("CSCSegAlgoST"), ps_(ps), showering_(nullptr) {
34  debug = ps.getUntrackedParameter<bool>("CSCDebug");
35  // minLayersApart = ps.getParameter<int>("minLayersApart");
36  // nSigmaFromSegment = ps.getParameter<double>("nSigmaFromSegment");
37  minHitsPerSegment = ps.getParameter<int>("minHitsPerSegment");
38  // muonsPerChamberMax = ps.getParameter<int>("CSCSegmentPerChamberMax");
39  // chi2Max = ps.getParameter<double>("chi2Max");
40  dXclusBoxMax = ps.getParameter<double>("dXclusBoxMax");
41  dYclusBoxMax = ps.getParameter<double>("dYclusBoxMax");
42  preClustering = ps.getParameter<bool>("preClustering");
43  preClustering_useChaining = ps.getParameter<bool>("preClusteringUseChaining");
44  Pruning = ps.getParameter<bool>("Pruning");
45  BrutePruning = ps.getParameter<bool>("BrutePruning");
46  BPMinImprovement = ps.getParameter<double>("BPMinImprovement");
47  // maxRecHitsInCluster is the maximal number of hits in a precluster that is being processed
48  // This cut is intended to remove messy events. Currently nothing is returned if there are
49  // more that maxRecHitsInCluster hits. It could be useful to return an estimate of the
50  // cluster position, which is available.
51  maxRecHitsInCluster = ps.getParameter<int>("maxRecHitsInCluster");
52  onlyBestSegment = ps.getParameter<bool>("onlyBestSegment");
53 
54  hitDropLimit4Hits = ps.getParameter<double>("hitDropLimit4Hits");
55  hitDropLimit5Hits = ps.getParameter<double>("hitDropLimit5Hits");
56  hitDropLimit6Hits = ps.getParameter<double>("hitDropLimit6Hits");
57 
58  yweightPenaltyThreshold = ps.getParameter<double>("yweightPenaltyThreshold");
59  yweightPenalty = ps.getParameter<double>("yweightPenalty");
60 
61  curvePenaltyThreshold = ps.getParameter<double>("curvePenaltyThreshold");
62  curvePenalty = ps.getParameter<double>("curvePenalty");
63 
64  useShowering = ps.getParameter<bool>("useShowering");
65  if (useShowering)
67 
69  adjustCovariance_ = ps.getParameter<bool>("CorrectTheErrors");
70 
71  chi2Norm_3D_ = ps.getParameter<double>("NormChi2Cut3D");
72  prePrun_ = ps.getParameter<bool>("prePrun");
73  prePrunLimit_ = ps.getParameter<double>("prePrunLimit");
74 
75  if (debug)
76  edm::LogVerbatim("CSCSegment") << "CSCSegAlgoST: with factored conditioned segment fit";
77 }
78 
79 /* Destructor
80  *
81  */
83 
84 std::vector<CSCSegment> CSCSegAlgoST::run(const CSCChamber* aChamber, const ChamberHitContainer& rechits) {
85  // Set member variable
86  theChamber = aChamber;
87 
88  LogTrace("CSCSegAlgoST") << "[CSCSegAlgoST::run] Start building segments in chamber " << theChamber->id();
89 
90  // pre-cluster rechits and loop over all sub clusters seperately
91  std::vector<CSCSegment> segments_temp;
92  std::vector<CSCSegment> segments;
93  std::vector<ChamberHitContainer> rechits_clusters; // a collection of clusters of rechits
94 
95  // Define yweight penalty depending on chamber.
96  // We fixed the relative ratios, but they can be scaled by parameters:
97 
98  for (int a = 0; a < 5; ++a) {
99  for (int b = 0; b < 5; ++b) {
100  a_yweightPenaltyThreshold[a][b] = 0.0;
101  }
102  }
103 
114 
115  if (preClustering) {
116  // run a pre-clusterer on the given rechits to split clearly-separated segment seeds:
118  // it uses X,Y,Z information; there are no configurable parameters used;
119  // the X, Y, Z "cuts" are just (much) wider than the LCT readout ones
120  // (which are actually not step functions); this new code could accomodate
121  // the clusterHits one below but we leave it for security and backward
122  // comparison reasons
123  rechits_clusters = chainHits(theChamber, rechits);
124  } else {
125  // it uses X,Y information + configurable parameters
126  rechits_clusters = clusterHits(theChamber, rechits);
127  }
128  // loop over the found clusters:
129  for (std::vector<ChamberHitContainer>::iterator sub_rechits = rechits_clusters.begin();
130  sub_rechits != rechits_clusters.end();
131  ++sub_rechits) {
132  // clear the buffer for the subset of segments:
133  segments_temp.clear();
134  // build the subset of segments:
135  segments_temp = buildSegments((*sub_rechits));
136  // add the found subset of segments to the collection of all segments in this chamber:
137  segments.insert(segments.end(), segments_temp.begin(), segments_temp.end());
138  }
139  // Any pruning of hits?
140  if (Pruning) {
141  segments_temp.clear(); // segments_temp needed?!?!
142  segments_temp = prune_bad_hits(theChamber, segments);
143  segments.clear(); // segments_temp needed?!?!
144  segments.swap(segments_temp); // segments_temp needed?!?!
145  }
146 
147  // Ganged strips in ME1/1A?
148  if (("ME1/a" == aChamber->specs()->chamberTypeName()) && aChamber->specs()->gangedStrips()) {
149  // if ( aChamber->specs()->gangedStrips() ){
150  findDuplicates(segments);
151  }
152  return segments;
153  } else {
154  segments = buildSegments(rechits);
155  if (Pruning) {
156  segments_temp.clear(); // segments_temp needed?!?!
157  segments_temp = prune_bad_hits(theChamber, segments);
158  segments.clear(); // segments_temp needed?!?!
159  segments.swap(segments_temp); // segments_temp needed?!?!
160  }
161 
162  // Ganged strips in ME1/1A?
163  if (("ME1/a" == aChamber->specs()->chamberTypeName()) && aChamber->specs()->gangedStrips()) {
164  // if ( aChamber->specs()->gangedStrips() ){
165  findDuplicates(segments);
166  }
167  return segments;
168  //return buildSegments(rechits);
169  }
170 }
171 
172 // ********************************************************************;
173 // *** This method is meant to remove clearly bad hits, using as ***;
174 // *** much information from the chamber as possible (e.g. charge, ***;
175 // *** hit position, timing, etc.) ***;
176 // ********************************************************************;
177 std::vector<CSCSegment> CSCSegAlgoST::prune_bad_hits(const CSCChamber* aChamber, std::vector<CSCSegment>& segments) {
178  // std::cout<<"*************************************************************"<<std::endl;
179  // std::cout<<"Called prune_bad_hits in Chamber "<< theChamber->specs()->chamberTypeName()<<std::endl;
180  // std::cout<<"*************************************************************"<<std::endl;
181 
182  std::vector<CSCSegment> segments_temp;
183  std::vector<ChamberHitContainer> rechits_clusters; // this is a collection of groups of rechits
184 
185  const float chi2ndfProbMin = 1.0e-4;
186  bool use_brute_force = BrutePruning;
187 
188  int hit_nr = 0;
189  int hit_nr_worst = -1;
190  //int hit_nr_2ndworst = -1;
191 
192  for (std::vector<CSCSegment>::iterator it = segments.begin(); it != segments.end(); ++it) {
193  // do nothing for nhit <= minHitPerSegment
194  if ((*it).nRecHits() <= minHitsPerSegment)
195  continue;
196 
197  if (!use_brute_force) { // find worst hit
198 
199  float chisq = (*it).chi2();
200  int nhits = (*it).nRecHits();
201  LocalPoint localPos = (*it).localPosition();
202  LocalVector segDir = (*it).localDirection();
203  const CSCChamber* cscchamber = theChamber;
204  float globZ;
205 
206  GlobalPoint globalPosition = cscchamber->toGlobal(localPos);
207  globZ = globalPosition.z();
208 
209  if (ChiSquaredProbability((double)chisq, (double)(2 * nhits - 4)) < chi2ndfProbMin) {
210  // find (rough) "residuals" (NOT excluding the hit from the fit - speed!) of hits on segment
211  std::vector<CSCRecHit2D> theseRecHits = (*it).specificRecHits();
212  std::vector<CSCRecHit2D>::const_iterator iRH_worst;
213  //float xdist_local = -99999.;
214 
215  float xdist_local_worst_sig = -99999.;
216  float xdist_local_2ndworst_sig = -99999.;
217  float xdist_local_sig = -99999.;
218 
219  hit_nr = 0;
220  hit_nr_worst = -1;
221  //hit_nr_2ndworst = -1;
222 
223  for (std::vector<CSCRecHit2D>::const_iterator iRH = theseRecHits.begin(); iRH != theseRecHits.end(); ++iRH) {
224  //mark "worst" hit:
225 
226  //float z_at_target ;
227  //float radius ;
228  float loc_x_at_target;
229  //float loc_y_at_target;
230  //float loc_z_at_target;
231 
232  //z_at_target = 0.;
233  //radius = 0.;
234 
235  // set the z target in CMS global coordinates:
236  const CSCLayer* csclayerRH = theChamber->layer((*iRH).cscDetId().layer());
237  LocalPoint localPositionRH = (*iRH).localPosition();
238  GlobalPoint globalPositionRH = csclayerRH->toGlobal(localPositionRH);
239 
240  LocalError rerrlocal = (*iRH).localPositionError();
241  float xxerr = rerrlocal.xx();
242 
243  float target_z = globalPositionRH.z(); // target z position in cm (z pos of the hit)
244 
245  if (target_z > 0.) {
246  loc_x_at_target = localPos.x() + (segDir.x() / fabs(segDir.z()) * (target_z - globZ));
247  //loc_y_at_target = localPos.y() + (segDir.y()/fabs(segDir.z())*( target_z - globZ ));
248  //loc_z_at_target = target_z;
249  } else {
250  loc_x_at_target = localPos.x() + ((-1) * segDir.x() / fabs(segDir.z()) * (target_z - globZ));
251  //loc_y_at_target = localPos.y() + ((-1)*segDir.y()/fabs(segDir.z())*( target_z - globZ ));
252  //loc_z_at_target = target_z;
253  }
254  // have to transform the segments coordinates back to the local frame... how?!!!!!!!!!!!!
255 
256  //xdist_local = fabs(localPositionRH.x() - loc_x_at_target);
257  xdist_local_sig = fabs((localPositionRH.x() - loc_x_at_target) / (xxerr));
258 
259  if (xdist_local_sig > xdist_local_worst_sig) {
260  xdist_local_2ndworst_sig = xdist_local_worst_sig;
261  xdist_local_worst_sig = xdist_local_sig;
262  iRH_worst = iRH;
263  //hit_nr_2ndworst = hit_nr_worst;
264  hit_nr_worst = hit_nr;
265  } else if (xdist_local_sig > xdist_local_2ndworst_sig) {
266  xdist_local_2ndworst_sig = xdist_local_sig;
267  //hit_nr_2ndworst = hit_nr;
268  }
269  ++hit_nr;
270  }
271 
272  // reset worst hit number if certain criteria apply.
273  // Criteria: 2nd worst hit must be at least a factor of
274  // 1.5 better than the worst in terms of sigma:
275  if (xdist_local_worst_sig / xdist_local_2ndworst_sig < 1.5) {
276  hit_nr_worst = -1;
277  //hit_nr_2ndworst = -1;
278  }
279  }
280  }
281 
282  // if worst hit was found, refit without worst hit and select if considerably better than original fit.
283  // Can also use brute force: refit all n-1 hit segments and choose one over the n hit if considerably "better"
284 
285  std::vector<CSCRecHit2D> buffer;
286  std::vector<std::vector<CSCRecHit2D> > reduced_segments;
287  std::vector<CSCRecHit2D> theseRecHits = (*it).specificRecHits();
288  float best_red_seg_prob = 0.0;
289  // usefor chi2 1 diff float best_red_seg_prob = 99999.;
290  buffer.clear();
291 
292  if (ChiSquaredProbability((double)(*it).chi2(), (double)((2 * (*it).nRecHits()) - 4)) < chi2ndfProbMin) {
293  buffer = theseRecHits;
294 
295  // Dirty switch: here one can select to refit all possible subsets or just the one without the
296  // tagged worst hit:
297  if (use_brute_force) { // Brute force method: loop over all possible segments:
298  for (size_t bi = 0; bi < buffer.size(); ++bi) {
299  reduced_segments.push_back(buffer);
300  reduced_segments[bi].erase(reduced_segments[bi].begin() + (bi), reduced_segments[bi].begin() + (bi + 1));
301  }
302  } else { // More elegant but still biased: erase only worst hit
303  // Comment: There is not a very strong correlation of the worst hit with the one that one should remove...
304  if (hit_nr_worst >= 0 && hit_nr_worst <= int(buffer.size())) {
305  // fill segment in buffer, delete worst hit
306  buffer.erase(buffer.begin() + (hit_nr_worst), buffer.begin() + (hit_nr_worst + 1));
307  reduced_segments.push_back(buffer);
308  } else {
309  // only fill segment in array, do not delete anything
310  reduced_segments.push_back(buffer);
311  }
312  }
313  }
314 
315  // Loop over the subsegments and fit (only one segment if "use_brute_force" is false):
316  for (size_t iSegment = 0; iSegment < reduced_segments.size(); ++iSegment) {
317  // loop over hits on given segment and push pointers to hits into protosegment
318  protoSegment.clear();
319  for (size_t m = 0; m < reduced_segments[iSegment].size(); ++m) {
320  protoSegment.push_back(&reduced_segments[iSegment][m]);
321  }
322 
323  // Create fitter object
324  CSCCondSegFit* segfit = new CSCCondSegFit(pset(), chamber(), protoSegment);
325  condpass1 = false;
326  condpass2 = false;
327  segfit->setScaleXError(1.0);
328  segfit->fit(condpass1, condpass2);
329 
330  // Attempt to handle numerical instability of the fit;
331  // The same as in the build method;
332  // Preprune is not applied;
333  if (adjustCovariance()) {
334  if (segfit->chi2() / segfit->ndof() > chi2Norm_3D_) {
335  condpass1 = true;
336  segfit->fit(condpass1, condpass2);
337  }
338  if ((segfit->scaleXError() < 1.00005) && (segfit->chi2() / segfit->ndof() > chi2Norm_3D_)) {
339  condpass2 = true;
340  segfit->fit(condpass1, condpass2);
341  }
342  }
343 
344  // calculate error matrix
345  // AlgebraicSymMatrix temp2 = segfit->covarianceMatrix();
346 
347  // build an actual segment
349  protoSegment, segfit->intercept(), segfit->localdir(), segfit->covarianceMatrix(), segfit->chi2());
350 
351  // and finished with this fit
352  delete segfit;
353 
354  // n-hit segment is (*it)
355  // (n-1)-hit segment is temp
356  // replace n-hit segment with (n-1)-hit segment if segment probability is BPMinImprovement better
357  double oldchi2 = (*it).chi2();
358  double olddof = 2 * (*it).nRecHits() - 4;
359  double newchi2 = temp.chi2();
360  double newdof = 2 * temp.nRecHits() - 4;
361  if ((ChiSquaredProbability(oldchi2, olddof) < (1. / BPMinImprovement) * ChiSquaredProbability(newchi2, newdof)) &&
362  (ChiSquaredProbability(newchi2, newdof) > best_red_seg_prob) &&
363  (ChiSquaredProbability(newchi2, newdof) > 1e-10)) {
364  best_red_seg_prob = ChiSquaredProbability(newchi2, newdof);
365  // The (n-1)- segment is better than the n-hit segment.
366  // If it has at least minHitsPerSegment hits replace the n-hit segment
367  // with this better (n-1)-hit segment:
368  if (temp.nRecHits() >= minHitsPerSegment) {
369  (*it) = temp;
370  }
371  }
372  } // end of loop over subsegments (iSegment)
373 
374  } // end loop over segments (it)
375 
376  return segments;
377 }
378 
379 // ********************************************************************;
380 std::vector<std::vector<const CSCRecHit2D*> > CSCSegAlgoST::clusterHits(const CSCChamber* aChamber,
381  const ChamberHitContainer& rechits) {
382  theChamber = aChamber;
383 
384  std::vector<ChamberHitContainer> rechits_clusters; // this is a collection of groups of rechits
385  // const float dXclus_box_cut = 4.; // seems to work reasonably 070116
386  // const float dYclus_box_cut = 8.; // seems to work reasonably 070116
387 
388  //float dXclus = 0.0;
389  //float dYclus = 0.0;
390  float dXclus_box = 0.0;
391  float dYclus_box = 0.0;
392 
393  std::vector<const CSCRecHit2D*> temp;
394 
395  std::vector<ChamberHitContainer> seeds;
396 
397  std::vector<float> running_meanX;
398  std::vector<float> running_meanY;
399 
400  std::vector<float> seed_minX;
401  std::vector<float> seed_maxX;
402  std::vector<float> seed_minY;
403  std::vector<float> seed_maxY;
404 
405  //std::cout<<"*************************************************************"<<std::endl;
406  //std::cout<<"Called clusterHits in Chamber "<< theChamber->specs()->chamberTypeName()<<std::endl;
407  //std::cout<<"*************************************************************"<<std::endl;
408 
409  // split rechits into subvectors and return vector of vectors:
410  // Loop over rechits
411  // Create one seed per hit
412  for (unsigned int i = 0; i < rechits.size(); ++i) {
413  temp.clear();
414 
415  temp.push_back(rechits[i]);
416 
417  seeds.push_back(temp);
418 
419  // First added hit in seed defines the mean to which the next hit is compared
420  // for this seed.
421 
422  running_meanX.push_back(rechits[i]->localPosition().x());
423  running_meanY.push_back(rechits[i]->localPosition().y());
424 
425  // set min/max X and Y for box containing the hits in the precluster:
426  seed_minX.push_back(rechits[i]->localPosition().x());
427  seed_maxX.push_back(rechits[i]->localPosition().x());
428  seed_minY.push_back(rechits[i]->localPosition().y());
429  seed_maxY.push_back(rechits[i]->localPosition().y());
430  }
431 
432  // merge clusters that are too close
433  // measure distance between final "running mean"
434  for (size_t NNN = 0; NNN < seeds.size(); ++NNN) {
435  for (size_t MMM = NNN + 1; MMM < seeds.size(); ++MMM) {
436  if (running_meanX[MMM] == 999999. || running_meanX[NNN] == 999999.) {
437  LogTrace("CSCSegment|CSC")
438  << "[CSCSegAlgoST::clusterHits] ALARM! Skipping used seeds, this should not happen - inform CSC DPG";
439  // std::cout<<"We should never see this line now!!!"<<std::endl;
440  continue; //skip seeds that have been used
441  }
442 
443  // calculate cut criteria for simple running mean distance cut:
444  //dXclus = fabs(running_meanX[NNN] - running_meanX[MMM]);
445  //dYclus = fabs(running_meanY[NNN] - running_meanY[MMM]);
446 
447  // calculate minmal distance between precluster boxes containing the hits:
448  if (running_meanX[NNN] > running_meanX[MMM])
449  dXclus_box = seed_minX[NNN] - seed_maxX[MMM];
450  else
451  dXclus_box = seed_minX[MMM] - seed_maxX[NNN];
452  if (running_meanY[NNN] > running_meanY[MMM])
453  dYclus_box = seed_minY[NNN] - seed_maxY[MMM];
454  else
455  dYclus_box = seed_minY[MMM] - seed_maxY[NNN];
456 
457  if (dXclus_box < dXclusBoxMax && dYclus_box < dYclusBoxMax) {
458  // merge clusters!
459  // merge by adding seed NNN to seed MMM and erasing seed NNN
460 
461  // calculate running mean for the merged seed:
462  running_meanX[MMM] = (running_meanX[NNN] * seeds[NNN].size() + running_meanX[MMM] * seeds[MMM].size()) /
463  (seeds[NNN].size() + seeds[MMM].size());
464  running_meanY[MMM] = (running_meanY[NNN] * seeds[NNN].size() + running_meanY[MMM] * seeds[MMM].size()) /
465  (seeds[NNN].size() + seeds[MMM].size());
466 
467  // update min/max X and Y for box containing the hits in the merged cluster:
468  if (seed_minX[NNN] <= seed_minX[MMM])
469  seed_minX[MMM] = seed_minX[NNN];
470  if (seed_maxX[NNN] > seed_maxX[MMM])
471  seed_maxX[MMM] = seed_maxX[NNN];
472  if (seed_minY[NNN] <= seed_minY[MMM])
473  seed_minY[MMM] = seed_minY[NNN];
474  if (seed_maxY[NNN] > seed_maxY[MMM])
475  seed_maxY[MMM] = seed_maxY[NNN];
476 
477  // add seed NNN to MMM (lower to larger number)
478  seeds[MMM].insert(seeds[MMM].end(), seeds[NNN].begin(), seeds[NNN].end());
479 
480  // mark seed NNN as used (at the moment just set running mean to 999999.)
481  running_meanX[NNN] = 999999.;
482  running_meanY[NNN] = 999999.;
483  // we have merged a seed (NNN) to the highter seed (MMM) - need to contimue to
484  // next seed (NNN+1)
485  break;
486  }
487  }
488  }
489 
490  // hand over the final seeds to the output
491  // would be more elegant if we could do the above step with
492  // erasing the merged ones, rather than the
493  for (size_t NNN = 0; NNN < seeds.size(); ++NNN) {
494  if (running_meanX[NNN] == 999999.)
495  continue; //skip seeds that have been marked as used up in merging
496  rechits_clusters.push_back(seeds[NNN]);
497  }
498 
499  //***************************************************************
500 
501  return rechits_clusters;
502 }
503 
504 std::vector<std::vector<const CSCRecHit2D*> > CSCSegAlgoST::chainHits(const CSCChamber* aChamber,
505  const ChamberHitContainer& rechits) {
506  std::vector<ChamberHitContainer> rechits_chains; // this is a collection of groups of rechits
507 
508  std::vector<const CSCRecHit2D*> temp;
509 
510  std::vector<ChamberHitContainer> seeds;
511 
512  std::vector<bool> usedCluster;
513 
514  // split rechits into subvectors and return vector of vectors:
515  // Loop over rechits
516  // Create one seed per hit
517  //std::cout<<" rechits.size() = "<<rechits.size()<<std::endl;
518  for (unsigned int i = 0; i < rechits.size(); ++i) {
519  temp.clear();
520  temp.push_back(rechits[i]);
521  seeds.push_back(temp);
522  usedCluster.push_back(false);
523  }
524  // Only ME1/1A can have ganged strips so no need to test name
525  bool gangedME11a = false;
526  if (("ME1/a" == aChamber->specs()->chamberTypeName()) && aChamber->specs()->gangedStrips()) {
527  // if ( aChamber->specs()->gangedStrips() ){
528  gangedME11a = true;
529  }
530  // merge chains that are too close ("touch" each other)
531  for (size_t NNN = 0; NNN < seeds.size(); ++NNN) {
532  for (size_t MMM = NNN + 1; MMM < seeds.size(); ++MMM) {
533  if (usedCluster[MMM] || usedCluster[NNN]) {
534  continue;
535  }
536  // all is in the way we define "good";
537  // try not to "cluster" the hits but to "chain" them;
538  // it does the clustering but also does a better job
539  // for inclined tracks (not clustering them together;
540  // crossed tracks would be still clustered together)
541  // 22.12.09: In fact it is not much more different
542  // than the "clustering", we just introduce another
543  // variable in the game - Z. And it makes sense
544  // to re-introduce Y (or actually wire group mumber)
545  // in a similar way as for the strip number - see
546  // the code below.
547  bool goodToMerge = isGoodToMerge(gangedME11a, seeds[NNN], seeds[MMM]);
548  if (goodToMerge) {
549  // merge chains!
550  // merge by adding seed NNN to seed MMM and erasing seed NNN
551 
552  // add seed NNN to MMM (lower to larger number)
553  seeds[MMM].insert(seeds[MMM].end(), seeds[NNN].begin(), seeds[NNN].end());
554 
555  // mark seed NNN as used
556  usedCluster[NNN] = true;
557  // we have merged a seed (NNN) to the highter seed (MMM) - need to contimue to
558  // next seed (NNN+1)
559  break;
560  }
561  }
562  }
563 
564  // hand over the final seeds to the output
565  // would be more elegant if we could do the above step with
566  // erasing the merged ones, rather than the
567 
568  for (size_t NNN = 0; NNN < seeds.size(); ++NNN) {
569  if (usedCluster[NNN])
570  continue; //skip seeds that have been marked as used up in merging
571  rechits_chains.push_back(seeds[NNN]);
572  }
573 
574  //***************************************************************
575 
576  return rechits_chains;
577 }
578 
580  for (size_t iRH_new = 0; iRH_new < newChain.size(); ++iRH_new) {
581  int layer_new = newChain[iRH_new]->cscDetId().layer() - 1;
582  int middleStrip_new = newChain[iRH_new]->nStrips() / 2;
583  int centralStrip_new = newChain[iRH_new]->channels(middleStrip_new);
584  int centralWire_new = newChain[iRH_new]->hitWire();
585  bool layerRequirementOK = false;
586  bool stripRequirementOK = false;
587  bool wireRequirementOK = false;
588  bool goodToMerge = false;
589  for (size_t iRH_old = 0; iRH_old < oldChain.size(); ++iRH_old) {
590  int layer_old = oldChain[iRH_old]->cscDetId().layer() - 1;
591  int middleStrip_old = oldChain[iRH_old]->nStrips() / 2;
592  int centralStrip_old = oldChain[iRH_old]->channels(middleStrip_old);
593  int centralWire_old = oldChain[iRH_old]->hitWire();
594 
595  // to be chained, two hits need to be in neighbouring layers...
596  // or better allow few missing layers (upto 3 to avoid inefficiencies);
597  // however we'll not make an angle correction because it
598  // worsen the situation in some of the "regular" cases
599  // (not making the correction means that the conditions for
600  // forming a cluster are different if we have missing layers -
601  // this could affect events at the boundaries )
602  if (layer_new == layer_old + 1 || layer_new == layer_old - 1 || layer_new == layer_old + 2 ||
603  layer_new == layer_old - 2 || layer_new == layer_old + 3 || layer_new == layer_old - 3 ||
604  layer_new == layer_old + 4 || layer_new == layer_old - 4) {
605  layerRequirementOK = true;
606  }
607  int allStrips = 48;
608  //to be chained, two hits need to be "close" in strip number (can do it in phi
609  // but it doesn't really matter); let "close" means upto 2 strips (3?) -
610  // this is more compared to what CLCT readout patterns allow
611  if (centralStrip_new == centralStrip_old || centralStrip_new == centralStrip_old + 1 ||
612  centralStrip_new == centralStrip_old - 1 || centralStrip_new == centralStrip_old + 2 ||
613  centralStrip_new == centralStrip_old - 2) {
614  stripRequirementOK = true;
615  }
616  // same for wires (and ALCT patterns)
617  if (centralWire_new == centralWire_old || centralWire_new == centralWire_old + 1 ||
618  centralWire_new == centralWire_old - 1 || centralWire_new == centralWire_old + 2 ||
619  centralWire_new == centralWire_old - 2) {
620  wireRequirementOK = true;
621  }
622 
623  if (gangedME11a) {
624  if (centralStrip_new == centralStrip_old + 1 - allStrips ||
625  centralStrip_new == centralStrip_old - 1 - allStrips ||
626  centralStrip_new == centralStrip_old + 2 - allStrips ||
627  centralStrip_new == centralStrip_old - 2 - allStrips ||
628  centralStrip_new == centralStrip_old + 1 + allStrips ||
629  centralStrip_new == centralStrip_old - 1 + allStrips ||
630  centralStrip_new == centralStrip_old + 2 + allStrips ||
631  centralStrip_new == centralStrip_old - 2 + allStrips) {
632  stripRequirementOK = true;
633  }
634  }
635  if (layerRequirementOK && stripRequirementOK && wireRequirementOK) {
636  goodToMerge = true;
637  return goodToMerge;
638  }
639  }
640  }
641  return false;
642 }
643 
645  double coordinate_1, double coordinate_2, double coordinate_3, float layer_1, float layer_2, float layer_3) {
646  double sub_weight = 0;
647  sub_weight = fabs(((coordinate_2 - coordinate_3) / (layer_2 - layer_3)) -
648  ((coordinate_1 - coordinate_2) / (layer_1 - layer_2)));
649  return sub_weight;
650 }
651 
652 /*
653  * This algorithm uses a Minimum Spanning Tree (ST) approach to build
654  * endcap muon track segments from the rechits in the 6 layers of a CSC.
655  */
656 std::vector<CSCSegment> CSCSegAlgoST::buildSegments(const ChamberHitContainer& rechits) {
657  // Clear buffer for segment vector
658  std::vector<CSCSegment> segmentInChamber;
659  segmentInChamber.clear(); // list of final segments
660 
661  // CSC Ring;
662  unsigned int thering = 999;
663  unsigned int thestation = 999;
664  //unsigned int thecham = 999;
665 
666  std::vector<int> hits_onLayerNumber(6);
667 
668  unsigned int UpperLimit = maxRecHitsInCluster;
669  if (int(rechits.size()) < minHitsPerSegment)
670  return segmentInChamber;
671 
672  for (int iarray = 0; iarray < 6; ++iarray) { // magic number 6: number of layers in CSC chamber - not gonna change :)
673  PAhits_onLayer[iarray].clear();
674  hits_onLayerNumber[iarray] = 0;
675  }
676 
677  chosen_Psegments.clear();
678  chosen_weight_A.clear();
679 
680  Psegments.clear();
681  Psegments_noLx.clear();
682  Psegments_noL1.clear();
683  Psegments_noL2.clear();
684  Psegments_noL3.clear();
685  Psegments_noL4.clear();
686  Psegments_noL5.clear();
687  Psegments_noL6.clear();
688 
689  Psegments_hits.clear();
690 
691  weight_A.clear();
692  weight_noLx_A.clear();
693  weight_noL1_A.clear();
694  weight_noL2_A.clear();
695  weight_noL3_A.clear();
696  weight_noL4_A.clear();
697  weight_noL5_A.clear();
698  weight_noL6_A.clear();
699 
700  weight_B.clear();
701  weight_noL1_B.clear();
702  weight_noL2_B.clear();
703  weight_noL3_B.clear();
704  weight_noL4_B.clear();
705  weight_noL5_B.clear();
706  weight_noL6_B.clear();
707 
708  curv_A.clear();
709  curv_noL1_A.clear();
710  curv_noL2_A.clear();
711  curv_noL3_A.clear();
712  curv_noL4_A.clear();
713  curv_noL5_A.clear();
714  curv_noL6_A.clear();
715 
716  // definition of middle layer for n-hit segment
717  int midlayer_pointer[6] = {0, 0, 2, 3, 3, 4};
718 
719  // int n_layers_missed_tot = 0;
720  int n_layers_occupied_tot = 0;
721  int n_layers_processed = 0;
722 
723  float min_weight_A = 99999.9;
724  float min_weight_noLx_A = 99999.9;
725 
726  //float best_weight_B = -1.;
727  //float best_weight_noLx_B = -1.;
728 
729  //float best_curv_A = -1.;
730  //float best_curv_noLx_A = -1.;
731 
732  int best_pseg = -1;
733  int best_noLx_pseg = -1;
734  int best_Layer_noLx = -1;
735 
736  //************************************************************************;
737  //*** Start segment building *****************************************;
738  //************************************************************************;
739 
740  // Determine how many layers with hits we have
741  // Fill all hits into the layer hit container:
742 
743  // Have 2 standard arrays: one giving the number of hits per layer.
744  // The other the corresponding hits.
745 
746  // Loop all available hits, count hits per layer and fill the hits into array by layer
747  for (size_t M = 0; M < rechits.size(); ++M) {
748  // add hits to array per layer and count hits per layer:
749  hits_onLayerNumber[rechits[M]->cscDetId().layer() - 1] += 1;
750  if (hits_onLayerNumber[rechits[M]->cscDetId().layer() - 1] == 1)
751  n_layers_occupied_tot += 1;
752  // add hits to vector in array
753  PAhits_onLayer[rechits[M]->cscDetId().layer() - 1].push_back(rechits[M]);
754  }
755 
756  // We have now counted the hits per layer and filled pointers to the hits into an array
757 
758  int tothits = 0;
759  int maxhits = 0;
760  int nexthits = 0;
761  int maxlayer = -1;
762  int nextlayer = -1;
763 
764  for (size_t i = 0; i < hits_onLayerNumber.size(); ++i) {
765  //std::cout<<"We have "<<hits_onLayerNumber[i]<<" hits on layer "<<i+1<<std::endl;
766  tothits += hits_onLayerNumber[i];
767  if (hits_onLayerNumber[i] > maxhits) {
768  nextlayer = maxlayer;
769  nexthits = maxhits;
770  maxlayer = i;
771  maxhits = hits_onLayerNumber[i];
772  } else if (hits_onLayerNumber[i] > nexthits) {
773  nextlayer = i;
774  nexthits = hits_onLayerNumber[i];
775  }
776  }
777 
778  if (tothits > (int)UpperLimit) {
779  if (n_layers_occupied_tot > 4) {
780  tothits = tothits - hits_onLayerNumber[maxlayer];
781  n_layers_occupied_tot = n_layers_occupied_tot - 1;
782  PAhits_onLayer[maxlayer].clear();
783  hits_onLayerNumber[maxlayer] = 0;
784  }
785  }
786 
787  if (tothits > (int)UpperLimit) {
788  if (n_layers_occupied_tot > 4) {
789  tothits = tothits - hits_onLayerNumber[nextlayer];
790  n_layers_occupied_tot = n_layers_occupied_tot - 1;
791  PAhits_onLayer[nextlayer].clear();
792  hits_onLayerNumber[nextlayer] = 0;
793  }
794  }
795 
796  if (tothits > (int)UpperLimit) {
797  //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
798  // Showering muon - returns nothing if chi2 == -1 (see comment in SegAlgoShowering)
799  //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
800  if (useShowering) {
801  CSCSegment segShower = showering_->showerSeg(theChamber, rechits);
802  if (debug)
803  dumpSegment(segShower);
804  // Make sure have at least 3 hits...
805  if (segShower.nRecHits() < 3)
806  return segmentInChamber;
807  if (segShower.chi2() == -1)
808  return segmentInChamber;
809  segmentInChamber.push_back(segShower);
810  return segmentInChamber;
811  } else {
812  // LogTrace("CSCSegment|CSC") << "[CSCSegAlgoST::buildSegments] No. of rechits in the cluster/chamber > "
813  // << UpperLimit << " ... Segment finding in the cluster/chamber canceled!";
814  CSCDetId id = rechits[0]->cscDetId();
815  edm::LogVerbatim("CSCSegment|CSC") << "[CSCSegAlgoST::buildSegments] No. of rechits in the cluster/chamber > "
816  << UpperLimit << " ... Segment finding canceled in CSC" << id;
817  return segmentInChamber;
818  }
819  }
820 
821  // Find out which station, ring and chamber we are in
822  // Used to choose station/ring dependant y-weight cuts
823 
824  if (!rechits.empty()) {
825  thering = rechits[0]->cscDetId().ring();
826  thestation = rechits[0]->cscDetId().station();
827  //thecham = rechits[0]->cscDetId().chamber();
828  }
829 
830  // std::cout<<"We are in Station/ring/chamber: "<<thestation <<" "<< thering<<" "<< thecham<<std::endl;
831 
832  // Cut-off parameter - don't reconstruct segments with less than X hits
833  if (n_layers_occupied_tot < minHitsPerSegment) {
834  return segmentInChamber;
835  }
836 
837  // Start building all possible hit combinations:
838 
839  // loop over the six chamber layers and form segment candidates from the available hits:
840 
841  for (int layer = 0; layer < 6; ++layer) {
842  // *****************************************************************
843  // *** Set missed layer counter here (not currently implemented) ***
844  // *****************************************************************
845  // if( PAhits_onLayer[layer].size() == 0 ) {
846  // n_layers_missed_tot += 1;
847  // }
848 
849  if (!PAhits_onLayer[layer].empty()) {
850  n_layers_processed += 1;
851  }
852 
853  // Save the size of the protosegment before hits were added on the current layer
854  int orig_number_of_psegs = Psegments.size();
855  int orig_number_of_noL1_psegs = Psegments_noL1.size();
856  int orig_number_of_noL2_psegs = Psegments_noL2.size();
857  int orig_number_of_noL3_psegs = Psegments_noL3.size();
858  int orig_number_of_noL4_psegs = Psegments_noL4.size();
859  int orig_number_of_noL5_psegs = Psegments_noL5.size();
860  int orig_number_of_noL6_psegs = Psegments_noL6.size();
861 
862  // loop over the hits on the layer and initiate protosegments or add hits to protosegments
863  for (int hit = 0; hit < int(PAhits_onLayer[layer].size()); ++hit) { // loop all hits on the Layer number "layer"
864 
865  // create protosegments from all hits on the first layer with hits
866  if (orig_number_of_psegs == 0) { // would be faster to turn this around - ask for "orig_number_of_psegs != 0"
867 
868  Psegments_hits.push_back(PAhits_onLayer[layer][hit]);
869 
870  Psegments.push_back(Psegments_hits);
871  Psegments_noL6.push_back(Psegments_hits);
872  Psegments_noL5.push_back(Psegments_hits);
873  Psegments_noL4.push_back(Psegments_hits);
874  Psegments_noL3.push_back(Psegments_hits);
875  Psegments_noL2.push_back(Psegments_hits);
876 
877  // Initialize weights corresponding to this segment for first hit (with 0)
878 
879  curv_A.push_back(0.0);
880  curv_noL6_A.push_back(0.0);
881  curv_noL5_A.push_back(0.0);
882  curv_noL4_A.push_back(0.0);
883  curv_noL3_A.push_back(0.0);
884  curv_noL2_A.push_back(0.0);
885 
886  weight_A.push_back(0.0);
887  weight_noL6_A.push_back(0.0);
888  weight_noL5_A.push_back(0.0);
889  weight_noL4_A.push_back(0.0);
890  weight_noL3_A.push_back(0.0);
891  weight_noL2_A.push_back(0.0);
892 
893  weight_B.push_back(0.0);
894  weight_noL6_B.push_back(0.0);
895  weight_noL5_B.push_back(0.0);
896  weight_noL4_B.push_back(0.0);
897  weight_noL3_B.push_back(0.0);
898  weight_noL2_B.push_back(0.0);
899 
900  // reset array for next hit on next layer
901  Psegments_hits.clear();
902  } else {
903  if (orig_number_of_noL1_psegs == 0) {
904  Psegments_hits.push_back(PAhits_onLayer[layer][hit]);
905 
906  Psegments_noL1.push_back(Psegments_hits);
907 
908  // Initialize weight corresponding to this segment for first hit (with 0)
909 
910  curv_noL1_A.push_back(0.0);
911 
912  weight_noL1_A.push_back(0.0);
913 
914  weight_noL1_B.push_back(0.0);
915 
916  // reset array for next hit on next layer
917  Psegments_hits.clear();
918  }
919 
920  // loop over the protosegments and create a new protosegments for each hit-1 on this layer
921 
922  for (int pseg = 0; pseg < orig_number_of_psegs; ++pseg) {
923  int pseg_pos = (pseg) + ((hit)*orig_number_of_psegs);
924  int pseg_noL1_pos = (pseg) + ((hit)*orig_number_of_noL1_psegs);
925  int pseg_noL2_pos = (pseg) + ((hit)*orig_number_of_noL2_psegs);
926  int pseg_noL3_pos = (pseg) + ((hit)*orig_number_of_noL3_psegs);
927  int pseg_noL4_pos = (pseg) + ((hit)*orig_number_of_noL4_psegs);
928  int pseg_noL5_pos = (pseg) + ((hit)*orig_number_of_noL5_psegs);
929  int pseg_noL6_pos = (pseg) + ((hit)*orig_number_of_noL6_psegs);
930 
931  // - Loop all psegs.
932  // - If not last hit, clone existing protosegments (PAhits_onLayer[layer].size()-1) times
933  // - then add the new hits
934 
935  if (!(hit == int(PAhits_onLayer[layer].size() -
936  1))) { // not the last hit - prepare (copy) new protosegments for the following hits
937  // clone psegs (to add next hits or last hit on layer):
938 
939  Psegments.push_back(Psegments[pseg_pos]);
940  if (n_layers_processed != 2 && pseg < orig_number_of_noL1_psegs)
941  Psegments_noL1.push_back(Psegments_noL1[pseg_noL1_pos]);
942  if (n_layers_processed != 2 && pseg < orig_number_of_noL2_psegs)
943  Psegments_noL2.push_back(Psegments_noL2[pseg_noL2_pos]);
944  if (n_layers_processed != 3 && pseg < orig_number_of_noL3_psegs)
945  Psegments_noL3.push_back(Psegments_noL3[pseg_noL3_pos]);
946  if (n_layers_processed != 4 && pseg < orig_number_of_noL4_psegs)
947  Psegments_noL4.push_back(Psegments_noL4[pseg_noL4_pos]);
948  if (n_layers_processed != 5 && pseg < orig_number_of_noL5_psegs)
949  Psegments_noL5.push_back(Psegments_noL5[pseg_noL5_pos]);
950  if (n_layers_processed != 6 && pseg < orig_number_of_noL6_psegs)
951  Psegments_noL6.push_back(Psegments_noL6[pseg_noL6_pos]);
952  // clone weight corresponding to this segment too
953  weight_A.push_back(weight_A[pseg_pos]);
954  if (n_layers_processed != 2 && pseg < orig_number_of_noL1_psegs)
955  weight_noL1_A.push_back(weight_noL1_A[pseg_noL1_pos]);
956  if (n_layers_processed != 2 && pseg < orig_number_of_noL2_psegs)
957  weight_noL2_A.push_back(weight_noL2_A[pseg_noL2_pos]);
958  if (n_layers_processed != 3 && pseg < orig_number_of_noL3_psegs)
959  weight_noL3_A.push_back(weight_noL3_A[pseg_noL3_pos]);
960  if (n_layers_processed != 4 && pseg < orig_number_of_noL4_psegs)
961  weight_noL4_A.push_back(weight_noL4_A[pseg_noL4_pos]);
962  if (n_layers_processed != 5 && pseg < orig_number_of_noL5_psegs)
963  weight_noL5_A.push_back(weight_noL5_A[pseg_noL5_pos]);
964  if (n_layers_processed != 6 && pseg < orig_number_of_noL6_psegs)
965  weight_noL6_A.push_back(weight_noL6_A[pseg_noL6_pos]);
966  // clone curvature variable corresponding to this segment too
967  curv_A.push_back(curv_A[pseg_pos]);
968  if (n_layers_processed != 2 && pseg < orig_number_of_noL1_psegs)
969  curv_noL1_A.push_back(curv_noL1_A[pseg_noL1_pos]);
970  if (n_layers_processed != 2 && pseg < orig_number_of_noL2_psegs)
971  curv_noL2_A.push_back(curv_noL2_A[pseg_noL2_pos]);
972  if (n_layers_processed != 3 && pseg < orig_number_of_noL3_psegs)
973  curv_noL3_A.push_back(curv_noL3_A[pseg_noL3_pos]);
974  if (n_layers_processed != 4 && pseg < orig_number_of_noL4_psegs)
975  curv_noL4_A.push_back(curv_noL4_A[pseg_noL4_pos]);
976  if (n_layers_processed != 5 && pseg < orig_number_of_noL5_psegs)
977  curv_noL5_A.push_back(curv_noL5_A[pseg_noL5_pos]);
978  if (n_layers_processed != 6 && pseg < orig_number_of_noL6_psegs)
979  curv_noL6_A.push_back(curv_noL6_A[pseg_noL6_pos]);
980  // clone "y"-weight corresponding to this segment too
981  weight_B.push_back(weight_B[pseg_pos]);
982  if (n_layers_processed != 2 && pseg < orig_number_of_noL1_psegs)
983  weight_noL1_B.push_back(weight_noL1_B[pseg_noL1_pos]);
984  if (n_layers_processed != 2 && pseg < orig_number_of_noL2_psegs)
985  weight_noL2_B.push_back(weight_noL2_B[pseg_noL2_pos]);
986  if (n_layers_processed != 3 && pseg < orig_number_of_noL3_psegs)
987  weight_noL3_B.push_back(weight_noL3_B[pseg_noL3_pos]);
988  if (n_layers_processed != 4 && pseg < orig_number_of_noL4_psegs)
989  weight_noL4_B.push_back(weight_noL4_B[pseg_noL4_pos]);
990  if (n_layers_processed != 5 && pseg < orig_number_of_noL5_psegs)
991  weight_noL5_B.push_back(weight_noL5_B[pseg_noL5_pos]);
992  if (n_layers_processed != 6 && pseg < orig_number_of_noL6_psegs)
993  weight_noL6_B.push_back(weight_noL6_B[pseg_noL6_pos]);
994  }
995  // add hits to original pseg:
996  Psegments[pseg_pos].push_back(PAhits_onLayer[layer][hit]);
997  if (n_layers_processed != 2 && pseg < orig_number_of_noL1_psegs)
998  Psegments_noL1[pseg_noL1_pos].push_back(PAhits_onLayer[layer][hit]);
999  if (n_layers_processed != 2 && pseg < orig_number_of_noL2_psegs)
1000  Psegments_noL2[pseg_noL2_pos].push_back(PAhits_onLayer[layer][hit]);
1001  if (n_layers_processed != 3 && pseg < orig_number_of_noL3_psegs)
1002  Psegments_noL3[pseg_noL3_pos].push_back(PAhits_onLayer[layer][hit]);
1003  if (n_layers_processed != 4 && pseg < orig_number_of_noL4_psegs)
1004  Psegments_noL4[pseg_noL4_pos].push_back(PAhits_onLayer[layer][hit]);
1005  if (n_layers_processed != 5 && pseg < orig_number_of_noL5_psegs)
1006  Psegments_noL5[pseg_noL5_pos].push_back(PAhits_onLayer[layer][hit]);
1007  if (n_layers_processed != 6 && pseg < orig_number_of_noL6_psegs)
1008  Psegments_noL6[pseg_noL6_pos].push_back(PAhits_onLayer[layer][hit]);
1009 
1010  // calculate/update the weight (only for >2 hits on psegment):
1011 
1012  if (Psegments[pseg_pos].size() > 2) {
1013  // looks more exciting than it is. Here the weight is calculated. It is the difference in x of the last two and one but the last two hits,
1014  // divided by the distance of the corresponding hits. Please refer to twiki page XXXX or CMS Note YYY (and use layer_distance)
1015 
1016  weight_A[pseg_pos] += theWeight((*(Psegments[pseg_pos].end() - 1))->localPosition().x(),
1017  (*(Psegments[pseg_pos].end() - 2))->localPosition().x(),
1018  (*(Psegments[pseg_pos].end() - 3))->localPosition().x(),
1019  float((*(Psegments[pseg_pos].end() - 1))->cscDetId().layer()),
1020  float((*(Psegments[pseg_pos].end() - 2))->cscDetId().layer()),
1021  float((*(Psegments[pseg_pos].end() - 3))->cscDetId().layer()));
1022 
1023  weight_B[pseg_pos] += theWeight((*(Psegments[pseg_pos].end() - 1))->localPosition().y(),
1024  (*(Psegments[pseg_pos].end() - 2))->localPosition().y(),
1025  (*(Psegments[pseg_pos].end() - 3))->localPosition().y(),
1026  float((*(Psegments[pseg_pos].end() - 1))->cscDetId().layer()),
1027  float((*(Psegments[pseg_pos].end() - 2))->cscDetId().layer()),
1028  float((*(Psegments[pseg_pos].end() - 3))->cscDetId().layer()));
1029 
1030  // if we have picked up the last hit go looking for pseg with the lowest (and second lowest?) weight
1031 
1032  if (int(Psegments[pseg_pos].size()) == n_layers_occupied_tot) {
1033  curv_A[pseg_pos] += theWeight(
1034  (*(Psegments[pseg_pos].end() - 1))->localPosition().x(),
1035  (*(Psegments[pseg_pos].end() - midlayer_pointer[n_layers_occupied_tot - 1]))->localPosition().x(),
1036  (*(Psegments[pseg_pos].end() - n_layers_occupied_tot))->localPosition().x(),
1037  float((*(Psegments[pseg_pos].end() - 1))->cscDetId().layer()),
1038  float(
1039  (*(Psegments[pseg_pos].end() - midlayer_pointer[n_layers_occupied_tot - 1]))->cscDetId().layer()),
1040  float((*(Psegments[pseg_pos].end() - n_layers_occupied_tot))->cscDetId().layer()));
1041 
1042  if (curv_A[pseg_pos] > curvePenaltyThreshold)
1043  weight_A[pseg_pos] = weight_A[pseg_pos] * curvePenalty;
1044 
1045  if (weight_B[pseg_pos] > a_yweightPenaltyThreshold[thestation][thering])
1046  weight_A[pseg_pos] = weight_A[pseg_pos] * yweightPenalty;
1047 
1048  if (weight_A[pseg_pos] < min_weight_A) {
1049  min_weight_A = weight_A[pseg_pos];
1050  //best_weight_B = weight_B[ pseg_pos ];
1051  //best_curv_A = curv_A[ pseg_pos ];
1052  best_pseg = pseg_pos;
1053  }
1054  }
1055 
1056  // alternative: fill map with weight and pseg (which is already ordered)? Seems a very good tool to go looking for segments from.
1057  // As I understand, the segments would be inserted according to their weight, so the list would "automatically" be sorted.
1058  }
1059 
1060  if (n_layers_occupied_tot > 3) {
1061  if (pseg < orig_number_of_noL1_psegs && (n_layers_processed != 2)) {
1062  if ((Psegments_noL1[pseg_noL1_pos].size() > 2)) {
1063  // looks more exciting than it is. Here the weight is calculated. It is the difference in x of the last two and one but the last two hits,
1064  // divided by the distance of the corresponding hits. Please refer to twiki page XXXX or CMS Note YYY (and use layer_distance)
1065 
1066  weight_noL1_A[pseg_noL1_pos] +=
1067  theWeight((*(Psegments_noL1[pseg_noL1_pos].end() - 1))->localPosition().x(),
1068  (*(Psegments_noL1[pseg_noL1_pos].end() - 2))->localPosition().x(),
1069  (*(Psegments_noL1[pseg_noL1_pos].end() - 3))->localPosition().x(),
1070  float((*(Psegments_noL1[pseg_noL1_pos].end() - 1))->cscDetId().layer()),
1071  float((*(Psegments_noL1[pseg_noL1_pos].end() - 2))->cscDetId().layer()),
1072  float((*(Psegments_noL1[pseg_noL1_pos].end() - 3))->cscDetId().layer()));
1073 
1074  weight_noL1_B[pseg_noL1_pos] +=
1075  theWeight((*(Psegments_noL1[pseg_noL1_pos].end() - 1))->localPosition().y(),
1076  (*(Psegments_noL1[pseg_noL1_pos].end() - 2))->localPosition().y(),
1077  (*(Psegments_noL1[pseg_noL1_pos].end() - 3))->localPosition().y(),
1078  float((*(Psegments_noL1[pseg_noL1_pos].end() - 1))->cscDetId().layer()),
1079  float((*(Psegments_noL1[pseg_noL1_pos].end() - 2))->cscDetId().layer()),
1080  float((*(Psegments_noL1[pseg_noL1_pos].end() - 3))->cscDetId().layer()));
1081 
1082  //if we have picked up the last hit go looking for pseg with the lowest (and second lowest?) weight
1083 
1084  if (int(Psegments_noL1[pseg_noL1_pos].size()) == n_layers_occupied_tot - 1) {
1085  curv_noL1_A[pseg_noL1_pos] += theWeight(
1086  (*(Psegments_noL1[pseg_noL1_pos].end() - 1))->localPosition().x(),
1087  (*(Psegments_noL1[pseg_noL1_pos].end() - midlayer_pointer[n_layers_occupied_tot - 2]))
1088  ->localPosition()
1089  .x(),
1090  (*(Psegments_noL1[pseg_noL1_pos].end() - (n_layers_occupied_tot - 1)))->localPosition().x(),
1091  float((*(Psegments_noL1[pseg_noL1_pos].end() - 1))->cscDetId().layer()),
1092  float((*(Psegments_noL1[pseg_noL1_pos].end() - midlayer_pointer[n_layers_occupied_tot - 2]))
1093  ->cscDetId()
1094  .layer()),
1095  float(
1096  (*(Psegments_noL1[pseg_noL1_pos].end() - (n_layers_occupied_tot - 1)))->cscDetId().layer()));
1097 
1098  if (curv_noL1_A[pseg_noL1_pos] > curvePenaltyThreshold)
1099  weight_noL1_A[pseg_noL1_pos] = weight_noL1_A[pseg_noL1_pos] * curvePenalty;
1100 
1101  if (weight_noL1_B[pseg_noL1_pos] > a_yweightPenaltyThreshold[thestation][thering])
1102  weight_noL1_A[pseg_noL1_pos] = weight_noL1_A[pseg_noL1_pos] * yweightPenalty;
1103 
1104  if (weight_noL1_A[pseg_noL1_pos] < min_weight_noLx_A) {
1105  min_weight_noLx_A = weight_noL1_A[pseg_noL1_pos];
1106  //best_weight_noLx_B = weight_noL1_B[ pseg_noL1_pos ];
1107  //best_curv_noLx_A = curv_noL1_A[ pseg_noL1_pos ];
1108  best_noLx_pseg = pseg_noL1_pos;
1109  best_Layer_noLx = 1;
1110  }
1111  }
1112 
1113  // alternative: fill map with weight and pseg (which is already ordered)? Seems a very good tool to go looking for segments from.
1114  // As I understand, the segments would be inserted according to their weight, so the list would "automatically" be sorted.
1115  }
1116  }
1117  }
1118 
1119  if (n_layers_occupied_tot > 3) {
1120  if (pseg < orig_number_of_noL2_psegs && (n_layers_processed != 2)) {
1121  if ((Psegments_noL2[pseg_noL2_pos].size() > 2)) {
1122  // looks more exciting than it is. Here the weight is calculated. It is the difference in x of the last two and one but the last two hits,
1123  // divided by the distance of the corresponding hits. Please refer to twiki page XXXX or CMS Note YYY (and use layer_distance)
1124 
1125  weight_noL2_A[pseg_noL2_pos] +=
1126  theWeight((*(Psegments_noL2[pseg_noL2_pos].end() - 1))->localPosition().x(),
1127  (*(Psegments_noL2[pseg_noL2_pos].end() - 2))->localPosition().x(),
1128  (*(Psegments_noL2[pseg_noL2_pos].end() - 3))->localPosition().x(),
1129  float((*(Psegments_noL2[pseg_noL2_pos].end() - 1))->cscDetId().layer()),
1130  float((*(Psegments_noL2[pseg_noL2_pos].end() - 2))->cscDetId().layer()),
1131  float((*(Psegments_noL2[pseg_noL2_pos].end() - 3))->cscDetId().layer()));
1132 
1133  weight_noL2_B[pseg_noL2_pos] +=
1134  theWeight((*(Psegments_noL2[pseg_noL2_pos].end() - 1))->localPosition().y(),
1135  (*(Psegments_noL2[pseg_noL2_pos].end() - 2))->localPosition().y(),
1136  (*(Psegments_noL2[pseg_noL2_pos].end() - 3))->localPosition().y(),
1137  float((*(Psegments_noL2[pseg_noL2_pos].end() - 1))->cscDetId().layer()),
1138  float((*(Psegments_noL2[pseg_noL2_pos].end() - 2))->cscDetId().layer()),
1139  float((*(Psegments_noL2[pseg_noL2_pos].end() - 3))->cscDetId().layer()));
1140 
1141  //if we have picked up the last hit go looking for pseg with the lowest (and second lowest?) weight
1142 
1143  if (int(Psegments_noL2[pseg_noL2_pos].size()) == n_layers_occupied_tot - 1) {
1144  curv_noL2_A[pseg_noL2_pos] += theWeight(
1145  (*(Psegments_noL2[pseg_noL2_pos].end() - 1))->localPosition().x(),
1146  (*(Psegments_noL2[pseg_noL2_pos].end() - midlayer_pointer[n_layers_occupied_tot - 2]))
1147  ->localPosition()
1148  .x(),
1149  (*(Psegments_noL2[pseg_noL2_pos].end() - (n_layers_occupied_tot - 1)))->localPosition().x(),
1150  float((*(Psegments_noL2[pseg_noL2_pos].end() - 1))->cscDetId().layer()),
1151  float((*(Psegments_noL2[pseg_noL2_pos].end() - midlayer_pointer[n_layers_occupied_tot - 2]))
1152  ->cscDetId()
1153  .layer()),
1154  float(
1155  (*(Psegments_noL2[pseg_noL2_pos].end() - (n_layers_occupied_tot - 1)))->cscDetId().layer()));
1156 
1157  if (curv_noL2_A[pseg_noL2_pos] > curvePenaltyThreshold)
1158  weight_noL2_A[pseg_noL2_pos] = weight_noL2_A[pseg_noL2_pos] * curvePenalty;
1159 
1160  if (weight_noL2_B[pseg_noL2_pos] > a_yweightPenaltyThreshold[thestation][thering])
1161  weight_noL2_A[pseg_noL2_pos] = weight_noL2_A[pseg_noL2_pos] * yweightPenalty;
1162 
1163  if (weight_noL2_A[pseg_noL2_pos] < min_weight_noLx_A) {
1164  min_weight_noLx_A = weight_noL2_A[pseg_noL2_pos];
1165  //best_weight_noLx_B = weight_noL2_B[ pseg_noL2_pos ];
1166  //best_curv_noLx_A = curv_noL2_A[ pseg_noL2_pos ];
1167  best_noLx_pseg = pseg_noL2_pos;
1168  best_Layer_noLx = 2;
1169  }
1170  }
1171 
1172  // alternative: fill map with weight and pseg (which is already ordered)? Seems a very good tool to go looking for segments from.
1173  // As I understand, the segments would be inserted according to their weight, so the list would "automatically" be sorted.
1174  }
1175  }
1176  }
1177 
1178  if (n_layers_occupied_tot > 3) {
1179  if (pseg < orig_number_of_noL3_psegs && (n_layers_processed != 3)) {
1180  if ((Psegments_noL3[pseg_noL3_pos].size() > 2)) {
1181  // looks more exciting than it is. Here the weight is calculated. It is the difference in x of the last two and one but the last two hits,
1182  // divided by the distance of the corresponding hits. Please refer to twiki page XXXX or CMS Note YYY (and use layer_distance)
1183 
1184  weight_noL3_A[pseg_noL3_pos] +=
1185  theWeight((*(Psegments_noL3[pseg_noL3_pos].end() - 1))->localPosition().x(),
1186  (*(Psegments_noL3[pseg_noL3_pos].end() - 2))->localPosition().x(),
1187  (*(Psegments_noL3[pseg_noL3_pos].end() - 3))->localPosition().x(),
1188  float((*(Psegments_noL3[pseg_noL3_pos].end() - 1))->cscDetId().layer()),
1189  float((*(Psegments_noL3[pseg_noL3_pos].end() - 2))->cscDetId().layer()),
1190  float((*(Psegments_noL3[pseg_noL3_pos].end() - 3))->cscDetId().layer()));
1191 
1192  weight_noL3_B[pseg_noL3_pos] +=
1193  theWeight((*(Psegments_noL3[pseg_noL3_pos].end() - 1))->localPosition().y(),
1194  (*(Psegments_noL3[pseg_noL3_pos].end() - 2))->localPosition().y(),
1195  (*(Psegments_noL3[pseg_noL3_pos].end() - 3))->localPosition().y(),
1196  float((*(Psegments_noL3[pseg_noL3_pos].end() - 1))->cscDetId().layer()),
1197  float((*(Psegments_noL3[pseg_noL3_pos].end() - 2))->cscDetId().layer()),
1198  float((*(Psegments_noL3[pseg_noL3_pos].end() - 3))->cscDetId().layer()));
1199 
1200  //if we have picked up the last hit go looking for pseg with the lowest (and second lowest?) weight
1201 
1202  if (int(Psegments_noL3[pseg_noL3_pos].size()) == n_layers_occupied_tot - 1) {
1203  curv_noL3_A[pseg_noL3_pos] += theWeight(
1204  (*(Psegments_noL3[pseg_noL3_pos].end() - 1))->localPosition().x(),
1205  (*(Psegments_noL3[pseg_noL3_pos].end() - midlayer_pointer[n_layers_occupied_tot - 2]))
1206  ->localPosition()
1207  .x(),
1208  (*(Psegments_noL3[pseg_noL3_pos].end() - (n_layers_occupied_tot - 1)))->localPosition().x(),
1209  float((*(Psegments_noL3[pseg_noL3_pos].end() - 1))->cscDetId().layer()),
1210  float((*(Psegments_noL3[pseg_noL3_pos].end() - midlayer_pointer[n_layers_occupied_tot - 2]))
1211  ->cscDetId()
1212  .layer()),
1213  float(
1214  (*(Psegments_noL3[pseg_noL3_pos].end() - (n_layers_occupied_tot - 1)))->cscDetId().layer()));
1215 
1216  if (curv_noL3_A[pseg_noL3_pos] > curvePenaltyThreshold)
1217  weight_noL3_A[pseg_noL3_pos] = weight_noL3_A[pseg_noL3_pos] * curvePenalty;
1218 
1219  if (weight_noL3_B[pseg_noL3_pos] > a_yweightPenaltyThreshold[thestation][thering])
1220  weight_noL3_A[pseg_noL3_pos] = weight_noL3_A[pseg_noL3_pos] * yweightPenalty;
1221 
1222  if (weight_noL3_A[pseg_noL3_pos] < min_weight_noLx_A) {
1223  min_weight_noLx_A = weight_noL3_A[pseg_noL3_pos];
1224  //best_weight_noLx_B = weight_noL3_B[ pseg_noL3_pos ];
1225  //best_curv_noLx_A = curv_noL3_A[ pseg_noL3_pos ];
1226  best_noLx_pseg = pseg_noL3_pos;
1227  best_Layer_noLx = 3;
1228  }
1229  }
1230 
1231  // alternative: fill map with weight and pseg (which is already ordered)? Seems a very good tool to go looking for segments from.
1232  // As I understand, the segments would be inserted according to their weight, so the list would "automatically" be sorted.
1233  }
1234  }
1235  }
1236 
1237  if (n_layers_occupied_tot > 3) {
1238  if (pseg < orig_number_of_noL4_psegs && (n_layers_processed != 4)) {
1239  if ((Psegments_noL4[pseg_noL4_pos].size() > 2)) {
1240  // looks more exciting than it is. Here the weight is calculated. It is the difference in x of the last two and one but the last two hits,
1241  // divided by the distance of the corresponding hits. Please refer to twiki page XXXX or CMS Note YYY (and use layer_distance)
1242 
1243  weight_noL4_A[pseg_noL4_pos] +=
1244  theWeight((*(Psegments_noL4[pseg_noL4_pos].end() - 1))->localPosition().x(),
1245  (*(Psegments_noL4[pseg_noL4_pos].end() - 2))->localPosition().x(),
1246  (*(Psegments_noL4[pseg_noL4_pos].end() - 3))->localPosition().x(),
1247  float((*(Psegments_noL4[pseg_noL4_pos].end() - 1))->cscDetId().layer()),
1248  float((*(Psegments_noL4[pseg_noL4_pos].end() - 2))->cscDetId().layer()),
1249  float((*(Psegments_noL4[pseg_noL4_pos].end() - 3))->cscDetId().layer()));
1250 
1251  weight_noL4_B[pseg_noL4_pos] +=
1252  theWeight((*(Psegments_noL4[pseg_noL4_pos].end() - 1))->localPosition().y(),
1253  (*(Psegments_noL4[pseg_noL4_pos].end() - 2))->localPosition().y(),
1254  (*(Psegments_noL4[pseg_noL4_pos].end() - 3))->localPosition().y(),
1255  float((*(Psegments_noL4[pseg_noL4_pos].end() - 1))->cscDetId().layer()),
1256  float((*(Psegments_noL4[pseg_noL4_pos].end() - 2))->cscDetId().layer()),
1257  float((*(Psegments_noL4[pseg_noL4_pos].end() - 3))->cscDetId().layer()));
1258 
1259  //if we have picked up the last hit go looking for pseg with the lowest (and second lowest?) weight
1260 
1261  if (int(Psegments_noL4[pseg_noL4_pos].size()) == n_layers_occupied_tot - 1) {
1262  curv_noL4_A[pseg_noL4_pos] += theWeight(
1263  (*(Psegments_noL4[pseg_noL4_pos].end() - 1))->localPosition().x(),
1264  (*(Psegments_noL4[pseg_noL4_pos].end() - midlayer_pointer[n_layers_occupied_tot - 2]))
1265  ->localPosition()
1266  .x(),
1267  (*(Psegments_noL4[pseg_noL4_pos].end() - (n_layers_occupied_tot - 1)))->localPosition().x(),
1268  float((*(Psegments_noL4[pseg_noL4_pos].end() - 1))->cscDetId().layer()),
1269  float((*(Psegments_noL4[pseg_noL4_pos].end() - midlayer_pointer[n_layers_occupied_tot - 2]))
1270  ->cscDetId()
1271  .layer()),
1272  float(
1273  (*(Psegments_noL4[pseg_noL4_pos].end() - (n_layers_occupied_tot - 1)))->cscDetId().layer()));
1274 
1275  if (curv_noL4_A[pseg_noL4_pos] > curvePenaltyThreshold)
1276  weight_noL4_A[pseg_noL4_pos] = weight_noL4_A[pseg_noL4_pos] * curvePenalty;
1277 
1278  if (weight_noL4_B[pseg_noL4_pos] > a_yweightPenaltyThreshold[thestation][thering])
1279  weight_noL4_A[pseg_noL4_pos] = weight_noL4_A[pseg_noL4_pos] * yweightPenalty;
1280 
1281  if (weight_noL4_A[pseg_noL4_pos] < min_weight_noLx_A) {
1282  min_weight_noLx_A = weight_noL4_A[pseg_noL4_pos];
1283  //best_weight_noLx_B = weight_noL4_B[ pseg_noL4_pos ];
1284  //best_curv_noLx_A = curv_noL4_A[ pseg_noL4_pos ];
1285  best_noLx_pseg = pseg_noL4_pos;
1286  best_Layer_noLx = 4;
1287  }
1288  }
1289 
1290  // alternative: fill map with weight and pseg (which is already ordered)? Seems a very good tool to go looking for segments from.
1291  // As I understand, the segments would be inserted according to their weight, so the list would "automatically" be sorted.
1292  }
1293  }
1294  }
1295 
1296  if (n_layers_occupied_tot > 4) {
1297  if (pseg < orig_number_of_noL5_psegs && (n_layers_processed != 5)) {
1298  if ((Psegments_noL5[pseg_noL5_pos].size() > 2)) {
1299  // looks more exciting than it is. Here the weight is calculated. It is the difference in x of the last two and one but the last two hits,
1300  // divided by the distance of the corresponding hits. Please refer to twiki page XXXX or CMS Note YYY (and use layer_distance)
1301 
1302  weight_noL5_A[pseg_noL5_pos] +=
1303  theWeight((*(Psegments_noL5[pseg_noL5_pos].end() - 1))->localPosition().x(),
1304  (*(Psegments_noL5[pseg_noL5_pos].end() - 2))->localPosition().x(),
1305  (*(Psegments_noL5[pseg_noL5_pos].end() - 3))->localPosition().x(),
1306  float((*(Psegments_noL5[pseg_noL5_pos].end() - 1))->cscDetId().layer()),
1307  float((*(Psegments_noL5[pseg_noL5_pos].end() - 2))->cscDetId().layer()),
1308  float((*(Psegments_noL5[pseg_noL5_pos].end() - 3))->cscDetId().layer()));
1309 
1310  weight_noL5_B[pseg_noL5_pos] +=
1311  theWeight((*(Psegments_noL5[pseg_noL5_pos].end() - 1))->localPosition().y(),
1312  (*(Psegments_noL5[pseg_noL5_pos].end() - 2))->localPosition().y(),
1313  (*(Psegments_noL5[pseg_noL5_pos].end() - 3))->localPosition().y(),
1314  float((*(Psegments_noL5[pseg_noL5_pos].end() - 1))->cscDetId().layer()),
1315  float((*(Psegments_noL5[pseg_noL5_pos].end() - 2))->cscDetId().layer()),
1316  float((*(Psegments_noL5[pseg_noL5_pos].end() - 3))->cscDetId().layer()));
1317 
1318  //if we have picked up the last hit go looking for pseg with the lowest (and second lowest?) weight
1319 
1320  if (int(Psegments_noL5[pseg_noL5_pos].size()) == n_layers_occupied_tot - 1) {
1321  curv_noL5_A[pseg_noL5_pos] += theWeight(
1322  (*(Psegments_noL5[pseg_noL5_pos].end() - 1))->localPosition().x(),
1323  (*(Psegments_noL5[pseg_noL5_pos].end() - midlayer_pointer[n_layers_occupied_tot - 2]))
1324  ->localPosition()
1325  .x(),
1326  (*(Psegments_noL5[pseg_noL5_pos].end() - (n_layers_occupied_tot - 1)))->localPosition().x(),
1327  float((*(Psegments_noL5[pseg_noL5_pos].end() - 1))->cscDetId().layer()),
1328  float((*(Psegments_noL5[pseg_noL5_pos].end() - midlayer_pointer[n_layers_occupied_tot - 2]))
1329  ->cscDetId()
1330  .layer()),
1331  float(
1332  (*(Psegments_noL5[pseg_noL5_pos].end() - (n_layers_occupied_tot - 1)))->cscDetId().layer()));
1333 
1334  if (curv_noL5_A[pseg_noL5_pos] > curvePenaltyThreshold)
1335  weight_noL5_A[pseg_noL5_pos] = weight_noL5_A[pseg_noL5_pos] * curvePenalty;
1336 
1337  if (weight_noL5_B[pseg_noL5_pos] > a_yweightPenaltyThreshold[thestation][thering])
1338  weight_noL5_A[pseg_noL5_pos] = weight_noL5_A[pseg_noL5_pos] * yweightPenalty;
1339 
1340  if (weight_noL5_A[pseg_noL5_pos] < min_weight_noLx_A) {
1341  min_weight_noLx_A = weight_noL5_A[pseg_noL5_pos];
1342  //best_weight_noLx_B = weight_noL5_B[ pseg_noL5_pos ];
1343  //best_curv_noLx_A = curv_noL5_A[ pseg_noL5_pos ];
1344  best_noLx_pseg = pseg_noL5_pos;
1345  best_Layer_noLx = 5;
1346  }
1347  }
1348 
1349  // alternative: fill map with weight and pseg (which is already ordered)? Seems a very good tool to go looking for segments from.
1350  // As I understand, the segments would be inserted according to their weight, so the list would "automatically" be sorted.
1351  }
1352  }
1353  }
1354 
1355  if (n_layers_occupied_tot > 5) {
1356  if (pseg < orig_number_of_noL6_psegs && (n_layers_processed != 6)) {
1357  if ((Psegments_noL6[pseg_noL6_pos].size() > 2)) {
1358  // looks more exciting than it is. Here the weight is calculated. It is the difference in x of the last two and one but the last two hits,
1359  // divided by the distance of the corresponding hits. Please refer to twiki page XXXX or CMS Note YYY (and use layer_distance)
1360 
1361  weight_noL6_A[pseg_noL6_pos] +=
1362  theWeight((*(Psegments_noL6[pseg_noL6_pos].end() - 1))->localPosition().x(),
1363  (*(Psegments_noL6[pseg_noL6_pos].end() - 2))->localPosition().x(),
1364  (*(Psegments_noL6[pseg_noL6_pos].end() - 3))->localPosition().x(),
1365  float((*(Psegments_noL6[pseg_noL6_pos].end() - 1))->cscDetId().layer()),
1366  float((*(Psegments_noL6[pseg_noL6_pos].end() - 2))->cscDetId().layer()),
1367  float((*(Psegments_noL6[pseg_noL6_pos].end() - 3))->cscDetId().layer()));
1368 
1369  weight_noL6_B[pseg_noL6_pos] +=
1370  theWeight((*(Psegments_noL6[pseg_noL6_pos].end() - 1))->localPosition().y(),
1371  (*(Psegments_noL6[pseg_noL6_pos].end() - 2))->localPosition().y(),
1372  (*(Psegments_noL6[pseg_noL6_pos].end() - 3))->localPosition().y(),
1373  float((*(Psegments_noL6[pseg_noL6_pos].end() - 1))->cscDetId().layer()),
1374  float((*(Psegments_noL6[pseg_noL6_pos].end() - 2))->cscDetId().layer()),
1375  float((*(Psegments_noL6[pseg_noL6_pos].end() - 3))->cscDetId().layer()));
1376 
1377  //if we have picked up the last hit go looking for pseg with the lowest (and second lowest?) weight
1378 
1379  if (int(Psegments_noL6[pseg_noL6_pos].size()) == n_layers_occupied_tot - 1) {
1380  curv_noL6_A[pseg_noL6_pos] += theWeight(
1381  (*(Psegments_noL6[pseg_noL6_pos].end() - 1))->localPosition().x(),
1382  (*(Psegments_noL6[pseg_noL6_pos].end() - midlayer_pointer[n_layers_occupied_tot - 2]))
1383  ->localPosition()
1384  .x(),
1385  (*(Psegments_noL6[pseg_noL6_pos].end() - (n_layers_occupied_tot - 1)))->localPosition().x(),
1386  float((*(Psegments_noL6[pseg_noL6_pos].end() - 1))->cscDetId().layer()),
1387  float((*(Psegments_noL6[pseg_noL6_pos].end() - midlayer_pointer[n_layers_occupied_tot - 2]))
1388  ->cscDetId()
1389  .layer()),
1390  float(
1391  (*(Psegments_noL6[pseg_noL6_pos].end() - (n_layers_occupied_tot - 1)))->cscDetId().layer()));
1392 
1393  if (curv_noL6_A[pseg_noL6_pos] > curvePenaltyThreshold)
1394  weight_noL6_A[pseg_noL6_pos] = weight_noL6_A[pseg_noL6_pos] * curvePenalty;
1395 
1396  if (weight_noL6_B[pseg_noL6_pos] > a_yweightPenaltyThreshold[thestation][thering])
1397  weight_noL6_A[pseg_noL6_pos] = weight_noL6_A[pseg_noL6_pos] * yweightPenalty;
1398 
1399  if (weight_noL6_A[pseg_noL6_pos] < min_weight_noLx_A) {
1400  min_weight_noLx_A = weight_noL6_A[pseg_noL6_pos];
1401  //best_weight_noLx_B = weight_noL6_B[ pseg_noL6_pos ];
1402  //best_curv_noLx_A = curv_noL6_A[ pseg_noL6_pos ];
1403  best_noLx_pseg = pseg_noL6_pos;
1404  best_Layer_noLx = 6;
1405  }
1406  }
1407 
1408  // alternative: fill map with weight and pseg (which is already ordered)? Seems a very good tool to go looking for segments from.
1409  // As I understand, the segments would be inserted according to their weight, so the list would "automatically" be sorted.
1410  }
1411  }
1412  }
1413  }
1414  }
1415  }
1416  }
1417 
1418  //************************************************************************;
1419  //*** End segment building *******************************************;
1420  //************************************************************************;
1421 
1422  // Important part! Here segment(s) are actually chosen. All the good segments
1423  // could be chosen or some (best) ones only (in order to save time).
1424 
1425  // Check if there is a segment with n-1 hits that has a signifcantly better
1426  // weight than the best n hit segment
1427 
1428  // IBL 070828: implicit assumption here is that there will always only be one segment per
1429  // cluster - if there are >1 we will need to find out which segment the alternative n-1 hit
1430  // protosegment belongs to!
1431 
1432  //float chosen_weight = min_weight_A;
1433  //float chosen_ywgt = best_weight_B;
1434  //float chosen_curv = best_curv_A;
1435  //int chosen_nlayers = n_layers_occupied_tot;
1436  int chosen_pseg = best_pseg;
1437  if (best_pseg < 0) {
1438  return segmentInChamber;
1439  }
1442 
1443  float hit_drop_limit = -999999.999;
1444 
1445  // define different weight improvement requirements depending on how many layers are in the segment candidate
1446  switch (n_layers_processed) {
1447  case 1:
1448  // do nothing;
1449  break;
1450  case 2:
1451  // do nothing;
1452  break;
1453  case 3:
1454  // do nothing;
1455  break;
1456  case 4:
1457  hit_drop_limit = hitDropLimit6Hits * (1. / 2.) * hitDropLimit4Hits;
1458  if ((best_Layer_noLx < 1) || (best_Layer_noLx > 4)) {
1459  // std::cout<<"CSCSegAlgoST: For four layers, best_Layer_noLx = "<< best_Layer_noLx << std::endl;
1460  }
1461  if ((best_Layer_noLx == 2) || (best_Layer_noLx == 3))
1462  hit_drop_limit = hit_drop_limit * (1. / 2.);
1463  break;
1464  case 5:
1465  hit_drop_limit = hitDropLimit6Hits * (2. / 3.) * hitDropLimit5Hits;
1466  if ((best_Layer_noLx < 1) || (best_Layer_noLx > 5)) {
1467  // std::cout<<"CSCSegAlgoST: For five layers, best_Layer_noLx = "<< best_Layer_noLx << std::endl;
1468  }
1469  if ((best_Layer_noLx == 2) || (best_Layer_noLx == 4))
1470  hit_drop_limit = hit_drop_limit * (1. / 2.);
1471  if (best_Layer_noLx == 3)
1472  hit_drop_limit = hit_drop_limit * (1. / 3.);
1473  break;
1474  case 6:
1475  hit_drop_limit = hitDropLimit6Hits * (3. / 4.);
1476  if ((best_Layer_noLx < 1) || (best_Layer_noLx > 6)) {
1477  // std::cout<<"CSCSegAlgoST: For six layers, best_Layer_noLx = "<< best_Layer_noLx << std::endl;
1478  }
1479  if ((best_Layer_noLx == 2) || (best_Layer_noLx == 5))
1480  hit_drop_limit = hit_drop_limit * (1. / 2.);
1481  if ((best_Layer_noLx == 3) || (best_Layer_noLx == 4))
1482  hit_drop_limit = hit_drop_limit * (1. / 3.);
1483  break;
1484 
1485  default:
1486  // Fallback - should never occur.
1487  LogTrace("CSCSegment|CSC")
1488  << "[CSCSegAlgoST::buildSegments] Unexpected number of layers with hits - please inform CSC DPG.";
1489  hit_drop_limit = 0.1;
1490  }
1491 
1492  // choose the NoLx collection (the one that contains the best N-1 candidate)
1493  switch (best_Layer_noLx) {
1494  case 1:
1495  Psegments_noLx.clear();
1497  weight_noLx_A.clear();
1499  break;
1500  case 2:
1501  Psegments_noLx.clear();
1503  weight_noLx_A.clear();
1505  break;
1506  case 3:
1507  Psegments_noLx.clear();
1509  weight_noLx_A.clear();
1511  break;
1512  case 4:
1513  Psegments_noLx.clear();
1515  weight_noLx_A.clear();
1517  break;
1518  case 5:
1519  Psegments_noLx.clear();
1521  weight_noLx_A.clear();
1523  break;
1524  case 6:
1525  Psegments_noLx.clear();
1527  weight_noLx_A.clear();
1529  break;
1530 
1531  default:
1532  // Fallback - should occur only for preclusters with only 3 layers with hits.
1533  Psegments_noLx.clear();
1534  weight_noLx_A.clear();
1535  }
1536 
1537  if (min_weight_A > 0.) {
1538  if (min_weight_noLx_A / min_weight_A < hit_drop_limit) {
1539  //chosen_weight = min_weight_noLx_A;
1540  //chosen_ywgt = best_weight_noLx_B;
1541  //chosen_curv = best_curv_noLx_A;
1542  //chosen_nlayers = n_layers_occupied_tot-1;
1543  chosen_pseg = best_noLx_pseg;
1544  chosen_Psegments.clear();
1545  chosen_weight_A.clear();
1548  }
1549  }
1550 
1551  if (onlyBestSegment) {
1552  ChooseSegments2a(chosen_Psegments, chosen_pseg);
1553  } else {
1555  }
1556 
1557  for (unsigned int iSegment = 0; iSegment < GoodSegments.size(); ++iSegment) {
1558  protoSegment = GoodSegments[iSegment];
1559 
1560  // Create new fitter object
1561  CSCCondSegFit* segfit = new CSCCondSegFit(pset(), chamber(), protoSegment);
1562  condpass1 = false;
1563  condpass2 = false;
1564  segfit->setScaleXError(1.0);
1565  segfit->fit(condpass1, condpass2);
1566 
1567  // Attempt to handle numerical instability of the fit.
1568  // (Any segment with chi2/dof > chi2Norm_3D_ is considered
1569  // as potentially suffering from numerical instability in fit.)
1570  if (adjustCovariance()) {
1571  // Call the fit with prefitting option:
1572  // First fit a straight line to X-Z coordinates and calculate chi2
1573  // This is done in CSCCondSegFit::correctTheCovX()
1574  // Scale up errors in X if this chi2 is too big (default 'too big' is >20);
1575  // Then refit XY-Z with the scaled-up X errors
1576  if (segfit->chi2() / segfit->ndof() > chi2Norm_3D_) {
1577  condpass1 = true;
1578  segfit->fit(condpass1, condpass2);
1579  }
1580  if (segfit->scaleXError() < 1.00005) {
1581  LogTrace("CSCWeirdSegment") << "[CSCSegAlgoST::buildSegments] Segment ErrXX scaled and refit " << std::endl;
1582  if (segfit->chi2() / segfit->ndof() > chi2Norm_3D_) {
1583  // Call the fit with direct adjustment of condition number;
1584  // If the attempt to improve fit by scaling up X error fails
1585  // call the procedure to make the condition number of M compatible with
1586  // the precision of X and Y measurements;
1587  // Achieved by decreasing abs value of the Covariance
1588  LogTrace("CSCWeirdSegment")
1589  << "[CSCSegAlgoST::buildSegments] Segment ErrXY changed to match cond. number and refit " << std::endl;
1590  condpass2 = true;
1591  segfit->fit(condpass1, condpass2);
1592  }
1593  }
1594  // Call the pre-pruning procedure;
1595  // If the attempt to improve fit by scaling up X error is successfull,
1596  // while scale factor for X errors is too big.
1597  // Prune the recHit inducing the biggest contribution into X-Z chi^2
1598  // and refit;
1599  if (prePrun_ && (sqrt(segfit->scaleXError()) > prePrunLimit_) && (segfit->nhits() > 3)) {
1600  LogTrace("CSCWeirdSegment")
1601  << "[CSCSegAlgoST::buildSegments] Scale factor chi2uCorrection too big, pre-Prune and refit " << std::endl;
1602  protoSegment.erase(protoSegment.begin() + segfit->worstHit(), protoSegment.begin() + segfit->worstHit() + 1);
1603 
1604  // Need to create new fitter object to repeat fit with fewer hits
1605  // Original code maintained current values of condpass1, condpass2, scaleXError - calc in CorrectTheCovX()
1606  //@@ DO THE SAME THING HERE, BUT IS THAT CORRECT?! It does make a difference.
1607  double tempcorr = segfit->scaleXError(); // save current value
1608  delete segfit;
1609  segfit = new CSCCondSegFit(pset(), chamber(), protoSegment);
1610  segfit->setScaleXError(tempcorr); // reset to previous value (rather than init to 1)
1611  segfit->fit(condpass1, condpass2);
1612  }
1613  }
1614 
1615  // calculate covariance matrix
1616  // AlgebraicSymMatrix temp2 = segfit->covarianceMatrix();
1617 
1618  // build an actual CSC segment
1619  CSCSegment temp(protoSegment, segfit->intercept(), segfit->localdir(), segfit->covarianceMatrix(), segfit->chi2());
1620  delete segfit;
1621 
1622  if (debug)
1623  dumpSegment(temp);
1624 
1625  segmentInChamber.push_back(temp);
1626  }
1627  return segmentInChamber;
1628 }
1629 
1630 void CSCSegAlgoST::ChooseSegments2a(std::vector<ChamberHitContainer>& chosen_segments, int chosen_seg) {
1631  // just return best segment
1632  GoodSegments.clear();
1633  GoodSegments.push_back(chosen_segments[chosen_seg]);
1634 }
1635 
1636 void CSCSegAlgoST::ChooseSegments3(std::vector<ChamberHitContainer>& chosen_segments,
1637  std::vector<float>& chosen_weight,
1638  int chosen_seg) {
1639  int SumCommonHits = 0;
1640  GoodSegments.clear();
1641  int nr_remaining_candidates;
1642  unsigned int nr_of_segment_candidates;
1643 
1644  nr_remaining_candidates = nr_of_segment_candidates = chosen_segments.size();
1645 
1646  // always select and return best protosegment:
1647  GoodSegments.push_back(chosen_segments[chosen_seg]);
1648 
1649  float chosen_weight_temp = 999999.;
1650  int chosen_seg_temp = -1;
1651 
1652  // try to find further segment candidates:
1653  while (nr_remaining_candidates > 0) {
1654  for (unsigned int iCand = 0; iCand < nr_of_segment_candidates; ++iCand) {
1655  //only compare current best to psegs that have not been marked bad:
1656  if (chosen_weight[iCand] < 0.)
1657  continue;
1658  SumCommonHits = 0;
1659 
1660  for (int ihits = 0; ihits < int(chosen_segments[iCand].size());
1661  ++ihits) { // iCand and iiCand NEED to have same nr of hits! (always have by construction)
1662  if (chosen_segments[iCand][ihits] == chosen_segments[chosen_seg][ihits]) {
1663  ++SumCommonHits;
1664  }
1665  }
1666 
1667  //mark a pseg bad:
1668  if (SumCommonHits > 1) { // needs to be a card; should be investigated first
1669  chosen_weight[iCand] = -1.;
1670  nr_remaining_candidates -= 1;
1671  } else {
1672  // save the protosegment with the smallest weight
1673  if (chosen_weight[iCand] < chosen_weight_temp) {
1674  chosen_weight_temp = chosen_weight[iCand];
1675  chosen_seg_temp = iCand;
1676  }
1677  }
1678  }
1679 
1680  if (chosen_seg_temp > -1)
1681  GoodSegments.push_back(chosen_segments[chosen_seg_temp]);
1682 
1683  chosen_seg = chosen_seg_temp;
1684  // re-initialze temporary best parameters
1685  chosen_weight_temp = 999999;
1686  chosen_seg_temp = -1;
1687  }
1688 }
1689 
1690 void CSCSegAlgoST::ChooseSegments2(int best_seg) {
1691  // std::vector <int> CommonHits(6); // nice concept :)
1692  std::vector<unsigned int> BadCandidate;
1693  int SumCommonHits = 0;
1694  GoodSegments.clear();
1695  BadCandidate.clear();
1696  for (unsigned int iCand = 0; iCand < Psegments.size(); ++iCand) {
1697  // skip here if segment was marked bad
1698  for (unsigned int iiCand = iCand + 1; iiCand < Psegments.size(); ++iiCand) {
1699  // skip here too if segment was marked bad
1700  SumCommonHits = 0;
1701  if (Psegments[iCand].size() != Psegments[iiCand].size()) {
1702  LogTrace("CSCSegment|CSC")
1703  << "[CSCSegAlgoST::ChooseSegments2] ALARM!! Should not happen - please inform CSC DPG";
1704  } else {
1705  for (int ihits = 0; ihits < int(Psegments[iCand].size());
1706  ++ihits) { // iCand and iiCand NEED to have same nr of hits! (alsways have by construction)
1707  if (Psegments[iCand][ihits] == Psegments[iiCand][ihits]) {
1708  ++SumCommonHits;
1709  }
1710  }
1711  }
1712  if (SumCommonHits > 1) {
1713  if (weight_A[iCand] > weight_A[iiCand]) { // use weight_A here
1714  BadCandidate.push_back(iCand);
1715  // rather mark segment bad by an array which is in sync with protosegments!! e.g. set weight = weight*1000 or have an addidional array or set it to weight *= -1
1716  } else {
1717  BadCandidate.push_back(iiCand);
1718  // rather mark segment bad by an array which is in sync with protosegments!! e.g. set weight = weight*1000 or have an addidional array or set it to weight *= -1
1719  }
1720  }
1721  }
1722  }
1723  bool discard;
1724  for (unsigned int isegm = 0; isegm < Psegments.size(); ++isegm) {
1725  // For best results another iteration/comparison over Psegments
1726  //should be applied here... It would make the program much slower.
1727  discard = false;
1728  for (unsigned int ibad = 0; ibad < BadCandidate.size(); ++ibad) {
1729  // can save this loop if we used an array in sync with Psegments!!!!
1730  if (isegm == BadCandidate[ibad]) {
1731  discard = true;
1732  }
1733  }
1734  if (!discard) {
1735  GoodSegments.push_back(Psegments[isegm]);
1736  }
1737  }
1738 }
1739 
1740 void CSCSegAlgoST::findDuplicates(std::vector<CSCSegment>& segments) {
1741  // this is intended for ME1/1a only - we have ghost segments because of the strips ganging
1742  // this function finds them (first the rechits by sharesInput() )
1743  // if a segment shares all the rechits with another segment it is a duplicate (even if
1744  // it has less rechits)
1745 
1746  for (std::vector<CSCSegment>::iterator it = segments.begin(); it != segments.end(); ++it) {
1747  std::vector<CSCSegment*> duplicateSegments;
1748  for (std::vector<CSCSegment>::iterator it2 = segments.begin(); it2 != segments.end(); ++it2) {
1749  //
1750  bool allShared = true;
1751  if (it != it2) {
1752  allShared = it->sharesRecHits(*it2);
1753  } else {
1754  allShared = false;
1755  }
1756  //
1757  if (allShared) {
1758  duplicateSegments.push_back(&(*it2));
1759  }
1760  }
1761  it->setDuplicateSegments(duplicateSegments);
1762  }
1763 }
1764 
1765 void CSCSegAlgoST::dumpSegment(const CSCSegment& seg) const {
1766  // Only called if pset value 'CSCDebug' is set in config
1767 
1768  edm::LogVerbatim("CSCSegment") << "CSCSegment in " << chamber()->id() << "\nlocal position = " << seg.localPosition()
1769  << "\nerror = " << seg.localPositionError()
1770  << "\nlocal direction = " << seg.localDirection()
1771  << "\nerror =" << seg.localDirectionError() << "\ncovariance matrix"
1772  << seg.parametersError() << "chi2/ndf = " << seg.chi2() << "/"
1773  << seg.degreesOfFreedom() << "\n#rechits = " << seg.specificRecHits().size()
1774  << "\ntime = " << seg.time();
1775 }
size
Write out results.
double yweightPenaltyThreshold
Definition: CSCSegAlgoST.h:181
std::vector< float > curv_noL1_A
Definition: CSCSegAlgoST.h:141
Log< level::Info, true > LogVerbatim
std::vector< CSCSegment > run(const CSCChamber *aChamber, const ChamberHitContainer &rechits) override
Definition: CSCSegAlgoST.cc:84
std::vector< float > curv_noL4_A
Definition: CSCSegAlgoST.h:144
T getParameter(std::string const &) const
Definition: ParameterSet.h:307
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
bool preClustering_useChaining
Definition: CSCSegAlgoST.h:168
float time() const
Definition: CSCSegment.cc:144
LocalPoint localPosition() const override
Definition: CSCSegment.h:39
std::vector< float > weight_noL1_B
Definition: CSCSegAlgoST.h:148
bool condpass1
Flag whether to &#39;improve&#39; covariance matrix.
Definition: CSCSegAlgoST.h:189
double dXclusBoxMax
Definition: CSCSegAlgoST.h:164
T z() const
Definition: PV3DBase.h:61
CSCSegment showerSeg(const CSCChamber *aChamber, const ChamberHitContainer &rechits)
const CSCChamber * theChamber
Definition: CSCSegAlgoST.h:116
std::vector< float > weight_A
Definition: CSCSegAlgoST.h:131
std::vector< float > weight_noL5_B
Definition: CSCSegAlgoST.h:152
void ChooseSegments2(int best_seg)
void ChooseSegments3(int best_seg)
LocalPoint intercept() const
Definition: CSCSegFit.h:84
int worstHit(void)
Definition: CSCCondSegFit.h:36
std::vector< ChamberHitContainer > Psegments_noL2
Definition: CSCSegAlgoST.h:125
int ndof(void) const
Definition: CSCSegFit.h:83
const edm::ParameterSet & pset(void) const
Definition: CSCSegAlgoST.h:82
CSCSegAlgoST(const edm::ParameterSet &ps)
Constructor.
Definition: CSCSegAlgoST.cc:32
bool isGoodToMerge(bool isME11a, ChamberHitContainer &newChain, ChamberHitContainer &oldChain)
std::vector< float > weight_noL6_B
Definition: CSCSegAlgoST.h:153
std::vector< ChamberHitContainer > Psegments_noL3
Definition: CSCSegAlgoST.h:126
std::string chamberTypeName() const
ChamberHitContainer protoSegment
Definition: CSCSegAlgoST.h:155
std::vector< float > curv_noL2_A
Definition: CSCSegAlgoST.h:142
std::vector< float > weight_noL1_A
Definition: CSCSegAlgoST.h:133
std::vector< std::vector< const CSCRecHit2D * > > clusterHits(const CSCChamber *aChamber, const ChamberHitContainer &rechits)
double chi2() const override
Chi2 of the segment fit.
Definition: CSCSegment.h:58
std::vector< float > curv_noL5_A
Definition: CSCSegAlgoST.h:145
#define LogTrace(id)
double hitDropLimit4Hits
Definition: CSCSegAlgoST.h:175
T getUntrackedParameter(std::string const &, T const &) const
std::vector< float > weight_B
Definition: CSCSegAlgoST.h:147
LocalVector localDirection() const override
Local direction.
Definition: CSCSegment.h:42
T x() const
Definition: PV3DBase.h:59
bool adjustCovariance_
Definition: CSCSegAlgoST.h:187
CSCSegAlgoShowering * showering_
Definition: CSCSegAlgoST.h:114
std::vector< float > weight_noL3_B
Definition: CSCSegAlgoST.h:150
double BPMinImprovement
Definition: CSCSegAlgoST.h:171
std::vector< float > curv_noL6_A
Definition: CSCSegAlgoST.h:146
T sqrt(T t)
Definition: SSEVec.h:23
const CSCChamber * chamber() const
Definition: CSCSegAlgoST.h:109
double curvePenaltyThreshold
Definition: CSCSegAlgoST.h:184
std::vector< std::vector< const CSCRecHit2D * > > chainHits(const CSCChamber *aChamber, const ChamberHitContainer &rechits)
double hitDropLimit6Hits
Definition: CSCSegAlgoST.h:177
std::vector< float > weight_noL3_A
Definition: CSCSegAlgoST.h:135
std::vector< float > chosen_weight_A
Definition: CSCSegAlgoST.h:139
std::vector< CSCSegment > buildSegments(const ChamberHitContainer &rechits)
float ChiSquaredProbability(double chiSquared, double nrDOF)
~CSCSegAlgoST() override
Destructor.
Definition: CSCSegAlgoST.cc:82
int nRecHits() const
Definition: CSCSegment.h:68
std::vector< CSCSegment > prune_bad_hits(const CSCChamber *aChamber, std::vector< CSCSegment > &segments)
std::vector< float > weight_noL4_A
Definition: CSCSegAlgoST.h:136
int degreesOfFreedom() const override
Degrees of freedom of the segment fit.
Definition: CSCSegment.h:62
std::vector< ChamberHitContainer > Psegments_noLx
Definition: CSCSegAlgoST.h:123
std::vector< const CSCRecHit2D * > ChamberHitContainer
Typedefs.
Definition: CSCSegAlgoST.h:36
bool onlyBestSegment
Definition: CSCSegAlgoST.h:172
std::vector< ChamberHitContainer > Psegments_noL6
Definition: CSCSegAlgoST.h:129
GlobalPoint toGlobal(const Local2DPoint &lp) const
Conversion to the global R.F. from the R.F. of the GeomDet.
Definition: GeomDet.h:49
std::vector< float > weight_noL4_B
Definition: CSCSegAlgoST.h:151
LocalError localDirectionError() const override
Error on the local direction.
Definition: CSCSegment.cc:52
Segments GoodSegments
Definition: CSCSegAlgoST.h:117
bool adjustCovariance(void)
Definition: CSCSegAlgoST.h:85
std::vector< float > curv_A
Definition: CSCSegAlgoST.h:140
int minHitsPerSegment
Definition: CSCSegAlgoST.h:161
std::vector< float > curv_noL3_A
Definition: CSCSegAlgoST.h:143
ChamberHitContainer Psegments_hits
Definition: CSCSegAlgoST.h:120
double dYclusBoxMax
Definition: CSCSegAlgoST.h:165
AlgebraicSymMatrix covarianceMatrix(void)
Definition: CSCSegFit.cc:352
void findDuplicates(std::vector< CSCSegment > &segments)
std::vector< ChamberHitContainer > Psegments_noL5
Definition: CSCSegAlgoST.h:128
std::vector< ChamberHitContainer > Psegments
Definition: CSCSegAlgoST.h:122
void setScaleXError(double factor)
Definition: CSCSegFit.h:67
double b
Definition: hdecay.h:120
AlgebraicSymMatrix parametersError() const override
Covariance matrix of parameters()
Definition: CSCSegment.h:49
double theWeight(double coordinate_1, double coordinate_2, double coordinate_3, float layer_1, float layer_2, float layer_3)
Utility functions.
std::vector< float > weight_noL5_A
Definition: CSCSegAlgoST.h:137
double curvePenalty
Definition: CSCSegAlgoST.h:185
std::vector< ChamberHitContainer > Psegments_noL1
Definition: CSCSegAlgoST.h:124
std::vector< float > weight_noL6_A
Definition: CSCSegAlgoST.h:138
bool prePrun_
Chi^2 normalization for the initial fit.
Definition: CSCSegAlgoST.h:193
double a
Definition: hdecay.h:121
bool preClustering
Definition: CSCSegAlgoST.h:167
double yweightPenalty
Definition: CSCSegAlgoST.h:182
const std::vector< CSCRecHit2D > & specificRecHits() const
Definition: CSCSegment.h:66
bool gangedStrips() const
LocalVector localdir() const
Definition: CSCSegFit.h:85
float a_yweightPenaltyThreshold[5][5]
Definition: CSCSegAlgoST.h:179
void ChooseSegments2a(std::vector< ChamberHitContainer > &best_segments, int best_seg)
int maxRecHitsInCluster
Definition: CSCSegAlgoST.h:166
void dumpSegment(const CSCSegment &seg) const
std::vector< ChamberHitContainer > Psegments_noL4
Definition: CSCSegAlgoST.h:127
double hitDropLimit5Hits
Definition: CSCSegAlgoST.h:176
LocalError localPositionError() const override
Definition: CSCSegment.cc:48
size_t nhits(void) const
Definition: CSCSegFit.h:81
double scaleXError(void) const
Definition: CSCSegFit.h:80
std::vector< float > weight_noL2_A
Definition: CSCSegAlgoST.h:134
std::vector< ChamberHitContainer > chosen_Psegments
Definition: CSCSegAlgoST.h:130
void fit(bool condpass1=false, bool condpass2=false)
const CSCChamberSpecs * specs() const
Definition: CSCChamber.h:39
std::vector< float > weight_noLx_A
Definition: CSCSegAlgoST.h:132
ChamberHitContainer PAhits_onLayer[6]
Definition: CSCSegAlgoST.h:119
float xx() const
Definition: LocalError.h:22
CSCDetId id() const
Get the (concrete) DetId.
Definition: CSCChamber.h:34
double chi2Norm_3D_
Definition: CSCSegAlgoST.h:191
std::vector< float > weight_noL2_B
Definition: CSCSegAlgoST.h:149
double prePrunLimit_
Definition: CSCSegAlgoST.h:195