CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
CSCSegAlgoST.cc
Go to the documentation of this file.
1 
10 #include "CSCSegAlgoST.h"
11 #include "CSCSegAlgoShowering.h"
12 
14 
16 
19 
21 
22 #include <algorithm>
23 #include <cmath>
24 #include <iostream>
25 #include <string>
26 
27 
28 /* constructor
29  *
30  */
32  CSCSegmentAlgorithm(ps), myName("CSCSegAlgoST"), showering_(0) {
33 
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) showering_ = new CSCSegAlgoShowering( ps );
66 
68  correctCov_ = ps.getParameter<bool>("CorrectTheErrors");
69  chi2Norm_2D_ = ps.getParameter<double>("NormChi2Cut2D");
70  chi2Norm_3D_ = ps.getParameter<double>("NormChi2Cut3D");
71  prePrun_ = ps.getParameter<bool>("prePrun");
72  prePrunLimit_ = ps.getParameter<double>("prePrunLimit");
73 
74  condSeed1_ = ps.getParameter<double>("SeedSmall");
75  condSeed2_ = ps.getParameter<double>("SeedBig");
76  covToAnyNumber_ = ps.getParameter<bool>("ForceCovariance");
77  covToAnyNumberAll_ = ps.getParameter<bool>("ForceCovarianceAll");
78  covAnyNumber_ = ps.getParameter<double>("Covariance");
79  passCondNumber=false;
80  passCondNumber_2=false;
82  maxContrIndex=0;
83  protoNDF = 1.;
84 
85 }
86 
87 /* Destructor
88  *
89  */
91  delete showering_;
92 }
93 
94 
95 std::vector<CSCSegment> CSCSegAlgoST::run(const CSCChamber* aChamber, const ChamberHitContainer& rechits) {
96 
97  // Set member variable
98  theChamber = aChamber;
99 
100  LogTrace("CSCSegAlgoST") << "[CSCSegAlgoST::run] Start building segments in chamber " << theChamber->id();
101 
102  // pre-cluster rechits and loop over all sub clusters seperately
103  std::vector<CSCSegment> segments_temp;
104  std::vector<CSCSegment> segments;
105  std::vector<ChamberHitContainer> rechits_clusters; // a collection of clusters of rechits
106 
107  // Define yweight penalty depending on chamber.
108  // We fixed the relative ratios, but they can be scaled by parameters:
109 
110  for(int a = 0; a<5; ++a) {
111  for(int b = 0; b<5; ++b) {
112  a_yweightPenaltyThreshold[a][b] = 0.0;
113  }
114  }
115 
125  a_yweightPenaltyThreshold[4][2] = yweightPenaltyThreshold * 20.40; //@@ ADD ME4/2 WITH RING 2 VALUE
126 
127  if(preClustering) {
128  // run a pre-clusterer on the given rechits to split clearly-separated segment seeds:
130  // it uses X,Y,Z information; there are no configurable parameters used;
131  // the X, Y, Z "cuts" are just (much) wider than the LCT readout ones
132  // (which are actually not step functions); this new code could accomodate
133  // the clusterHits one below but we leave it for security and backward
134  // comparison reasons
135  rechits_clusters = chainHits( theChamber, rechits );
136  }
137  else{
138  // it uses X,Y information + configurable parameters
139  rechits_clusters = clusterHits( theChamber, rechits );
140  }
141  // loop over the found clusters:
142  for(std::vector<ChamberHitContainer>::iterator sub_rechits = rechits_clusters.begin(); sub_rechits != rechits_clusters.end(); ++sub_rechits ) {
143  // clear the buffer for the subset of segments:
144  segments_temp.clear();
145  // build the subset of segments:
146  segments_temp = buildSegments( (*sub_rechits) );
147  // add the found subset of segments to the collection of all segments in this chamber:
148  segments.insert( segments.end(), segments_temp.begin(), segments_temp.end() );
149  }
150  // Any pruning of hits?
151  if( Pruning ) {
152  segments_temp.clear(); // segments_temp needed?!?!
153  segments_temp = prune_bad_hits( theChamber, segments );
154  segments.clear(); // segments_temp needed?!?!
155  segments.swap(segments_temp); // segments_temp needed?!?!
156  }
157 
158  //@@ Ganged strips in ME1/1A?
159  if ( ("ME1/a" == aChamber->specs()->chamberTypeName()) && aChamber->specs()->gangedStrips() ){
160  // if ( aChamber->specs()->gangedStrips() ){
161  findDuplicates(segments);
162  }
163  return segments;
164  }
165  else {
166  segments = buildSegments(rechits);
167  if( Pruning ) {
168  segments_temp.clear(); // segments_temp needed?!?!
169  segments_temp = prune_bad_hits( theChamber, segments );
170  segments.clear(); // segments_temp needed?!?!
171  segments.swap(segments_temp); // segments_temp needed?!?!
172  }
173 
174  //@@ Ganged strips in ME1/1A?
175  if ( ("ME1/a" == aChamber->specs()->chamberTypeName()) && aChamber->specs()->gangedStrips() ){
176  // if ( aChamber->specs()->gangedStrips() ){
177  findDuplicates(segments);
178  }
179  return segments;
180  //return buildSegments(rechits);
181  }
182 }
183 
184 // ********************************************************************;
185 // *** This method is meant to remove clearly bad hits, using as ***;
186 // *** much information from the chamber as possible (e.g. charge, ***;
187 // *** hit position, timing, etc.) ***;
188 // ********************************************************************;
189 std::vector<CSCSegment> CSCSegAlgoST::prune_bad_hits(const CSCChamber* aChamber, std::vector<CSCSegment> & segments) {
190 
191  // std::cout<<"*************************************************************"<<std::endl;
192  // std::cout<<"Called prune_bad_hits in Chamber "<< theChamber->specs()->chamberTypeName()<<std::endl;
193  // std::cout<<"*************************************************************"<<std::endl;
194 
195  std::vector<CSCSegment> segments_temp;
196  std::vector<ChamberHitContainer> rechits_clusters; // this is a collection of groups of rechits
197 
198  const float chi2ndfProbMin = 1.0e-4;
199  bool use_brute_force = BrutePruning;
200 
201  int hit_nr = 0;
202  int hit_nr_worst = -1;
203  //int hit_nr_2ndworst = -1;
204 
205  for(std::vector<CSCSegment>::iterator it=segments.begin(); it != segments.end(); ++it) {
206 
207  // do nothing for nhit <= minHitPerSegment
208  if( (*it).nRecHits() <= minHitsPerSegment ) continue;
209 
210  if( !use_brute_force ) {// find worst hit
211 
212  float chisq = (*it).chi2();
213  int nhits = (*it).nRecHits();
214  LocalPoint localPos = (*it).localPosition();
215  LocalVector segDir = (*it).localDirection();
216  const CSCChamber* cscchamber = theChamber;
217  float globZ ;
218 
219  GlobalPoint globalPosition = cscchamber->toGlobal(localPos);
220  globZ = globalPosition.z();
221 
222 
223  if( ChiSquaredProbability((double)chisq,(double)(2*nhits-4)) < chi2ndfProbMin ) {
224 
225  // find (rough) "residuals" (NOT excluding the hit from the fit - speed!) of hits on segment
226  std::vector<CSCRecHit2D> theseRecHits = (*it).specificRecHits();
227  std::vector<CSCRecHit2D>::const_iterator iRH_worst;
228  //float xdist_local = -99999.;
229 
230  float xdist_local_worst_sig = -99999.;
231  float xdist_local_2ndworst_sig = -99999.;
232  float xdist_local_sig = -99999.;
233 
234  hit_nr = 0;
235  hit_nr_worst = -1;
236  //hit_nr_2ndworst = -1;
237 
238  for ( std::vector<CSCRecHit2D>::const_iterator iRH = theseRecHits.begin(); iRH != theseRecHits.end(); ++iRH) {
239  //mark "worst" hit:
240 
241  //float z_at_target ;
242  //float radius ;
243  float loc_x_at_target ;
244  //float loc_y_at_target ;
245  //float loc_z_at_target ;
246 
247  //z_at_target = 0.;
248  loc_x_at_target = 0.;
249  //loc_y_at_target = 0.;
250  //loc_z_at_target = 0.;
251  //radius = 0.;
252 
253  // set the z target in CMS global coordinates:
254  const CSCLayer* csclayerRH = theChamber->layer((*iRH).cscDetId().layer());
255  LocalPoint localPositionRH = (*iRH).localPosition();
256  GlobalPoint globalPositionRH = csclayerRH->toGlobal(localPositionRH);
257 
258  LocalError rerrlocal = (*iRH).localPositionError();
259  float xxerr = rerrlocal.xx();
260 
261  float target_z = globalPositionRH.z(); // target z position in cm (z pos of the hit)
262 
263  if(target_z > 0.) {
264  loc_x_at_target = localPos.x() + (segDir.x()/fabs(segDir.z())*( target_z - globZ ));
265  //loc_y_at_target = localPos.y() + (segDir.y()/fabs(segDir.z())*( target_z - globZ ));
266  //loc_z_at_target = target_z;
267  }
268  else {
269  loc_x_at_target = localPos.x() + ((-1)*segDir.x()/fabs(segDir.z())*( target_z - globZ ));
270  //loc_y_at_target = localPos.y() + ((-1)*segDir.y()/fabs(segDir.z())*( target_z - globZ ));
271  //loc_z_at_target = target_z;
272  }
273  // have to transform the segments coordinates back to the local frame... how?!!!!!!!!!!!!
274 
275  //xdist_local = fabs(localPositionRH.x() - loc_x_at_target);
276  xdist_local_sig = fabs((localPositionRH.x() -loc_x_at_target)/(xxerr));
277 
278  if( xdist_local_sig > xdist_local_worst_sig ) {
279  xdist_local_2ndworst_sig = xdist_local_worst_sig;
280  xdist_local_worst_sig = xdist_local_sig;
281  iRH_worst = iRH;
282  //hit_nr_2ndworst = hit_nr_worst;
283  hit_nr_worst = hit_nr;
284  }
285  else if(xdist_local_sig > xdist_local_2ndworst_sig) {
286  xdist_local_2ndworst_sig = xdist_local_sig;
287  //hit_nr_2ndworst = hit_nr;
288  }
289  ++hit_nr;
290  }
291 
292  // reset worst hit number if certain criteria apply.
293  // Criteria: 2nd worst hit must be at least a factor of
294  // 1.5 better than the worst in terms of sigma:
295  if ( xdist_local_worst_sig / xdist_local_2ndworst_sig < 1.5 ) {
296  hit_nr_worst = -1;
297  //hit_nr_2ndworst = -1;
298  }
299  }
300  }
301 
302  // if worst hit was found, refit without worst hit and select if considerably better than original fit.
303  // Can also use brute force: refit all n-1 hit segments and choose one over the n hit if considerably "better"
304 
305  std::vector< CSCRecHit2D > buffer;
306  std::vector< std::vector< CSCRecHit2D > > reduced_segments;
307  std::vector< CSCRecHit2D > theseRecHits = (*it).specificRecHits();
308  float best_red_seg_prob = 0.0;
309  // usefor chi2 1 diff float best_red_seg_prob = 99999.;
310  buffer.clear();
311 
312  if( ChiSquaredProbability((double)(*it).chi2(),(double)((2*(*it).nRecHits())-4)) < chi2ndfProbMin ) {
313 
314  buffer = theseRecHits;
315 
316  // Dirty switch: here one can select to refit all possible subsets or just the one without the
317  // tagged worst hit:
318  if( use_brute_force ) { // Brute force method: loop over all possible segments:
319  for(size_t bi = 0; bi < buffer.size(); ++bi) {
320  reduced_segments.push_back(buffer);
321  reduced_segments[bi].erase(reduced_segments[bi].begin()+(bi),reduced_segments[bi].begin()+(bi+1));
322  }
323  }
324  else { // More elegant but still biased: erase only worst hit
325  // Comment: There is not a very strong correlation of the worst hit with the one that one should remove...
326  if( hit_nr_worst >= 0 && hit_nr_worst <= int(buffer.size()) ) {
327  // fill segment in buffer, delete worst hit
328  buffer.erase(buffer.begin()+(hit_nr_worst),buffer.begin()+(hit_nr_worst+1));
329  reduced_segments.push_back(buffer);
330  }
331  else {
332  // only fill segment in array, do not delete anything
333  reduced_segments.push_back(buffer);
334  }
335  }
336  }
337 
338  // Loop over the subsegments and fit (only one segment if "use_brute_force" is false):
339  for(size_t iSegment=0; iSegment<reduced_segments.size(); ++iSegment) {
340  // loop over hits on given segment and push pointers to hits into protosegment
341  protoSegment.clear();
342  for(size_t m = 0; m<reduced_segments[iSegment].size(); ++m ) {
343  protoSegment.push_back(&reduced_segments[iSegment][m]);
344  }
345  passCondNumber=false;
346  passCondNumber_2 = false;
348  doSlopesAndChi2();
349  // Attempt to handle numerical instability of the fit;
350  // The same as in the build method;
351  // Preprune is not applied;
352  if(correctCov_){
354  passCondNumber = true;
355  doSlopesAndChi2();
356  }
358  passCondNumber_2=true;
359  doSlopesAndChi2();
360  }
361  }
363  // calculate error matrix
364  // AlgebraicSymMatrix protoErrors = calculateError();
365  SMatrixSym4 protoErrors = calculateError();
366  // but reorder components to match what's required by TrackingRecHit interface
367  // i.e. slopes first, then positions
368  AlgebraicSymMatrix temp2 = flipErrors( protoErrors ); //@@ TO SATISFY CSCSegment INTERFACE
369 
371 
372  // replace n hit segment with n-1 hit segment, if segment probability is BPMinImprovement better:
373  if( ( ChiSquaredProbability((double)(*it).chi2(),(double)((2*(*it).nRecHits())-4))
374  <
375  (1./BPMinImprovement)*(ChiSquaredProbability((double)temp.chi2(),(double)(2*temp.nRecHits()-4))) ) // was (1.e-3) 081202
376 
377  &&
378  ( (ChiSquaredProbability((double)temp.chi2(),(double)(2*temp.nRecHits()-4)))
379  > best_red_seg_prob
380  )
381  &&
382  ( (ChiSquaredProbability((double)temp.chi2(),(double)(2*temp.nRecHits()-4))) > 1e-10 )
383  ) {
384  best_red_seg_prob = ChiSquaredProbability((double)temp.chi2(),(double)(2*temp.nRecHits()-4));
385  // The alternative n-1 segment is much cleaner. If this segment
386  // has >= minHitsPerSegment hits exchange current n hit segment (*it)
387  // with better n-1 hit segment:
388  if( temp.nRecHits() >= minHitsPerSegment ) {
389  (*it) = temp;
390  }
391  }
392  }
393  }
394 
395  return segments;
396 
397 }
398 
399 
400 // ********************************************************************;
401 std::vector< std::vector<const CSCRecHit2D*> > CSCSegAlgoST::clusterHits(const CSCChamber* aChamber, const ChamberHitContainer & rechits) {
402  theChamber = aChamber;
403 
404  std::vector<ChamberHitContainer> rechits_clusters; // this is a collection of groups of rechits
405  // const float dXclus_box_cut = 4.; // seems to work reasonably 070116
406  // const float dYclus_box_cut = 8.; // seems to work reasonably 070116
407 
408  //float dXclus = 0.0;
409  //float dYclus = 0.0;
410  float dXclus_box = 0.0;
411  float dYclus_box = 0.0;
412 
413  std::vector<const CSCRecHit2D*> temp;
414 
415  std::vector< ChamberHitContainer > seeds;
416 
417  std::vector<float> running_meanX;
418  std::vector<float> running_meanY;
419 
420  std::vector<float> seed_minX;
421  std::vector<float> seed_maxX;
422  std::vector<float> seed_minY;
423  std::vector<float> seed_maxY;
424 
425  //std::cout<<"*************************************************************"<<std::endl;
426  //std::cout<<"Called clusterHits in Chamber "<< theChamber->specs()->chamberTypeName()<<std::endl;
427  //std::cout<<"*************************************************************"<<std::endl;
428 
429  // split rechits into subvectors and return vector of vectors:
430  // Loop over rechits
431  // Create one seed per hit
432  for(unsigned int i = 0; i < rechits.size(); ++i) {
433 
434  temp.clear();
435 
436  temp.push_back(rechits[i]);
437 
438  seeds.push_back(temp);
439 
440  // First added hit in seed defines the mean to which the next hit is compared
441  // for this seed.
442 
443  running_meanX.push_back( rechits[i]->localPosition().x() );
444  running_meanY.push_back( rechits[i]->localPosition().y() );
445 
446  // set min/max X and Y for box containing the hits in the precluster:
447  seed_minX.push_back( rechits[i]->localPosition().x() );
448  seed_maxX.push_back( rechits[i]->localPosition().x() );
449  seed_minY.push_back( rechits[i]->localPosition().y() );
450  seed_maxY.push_back( rechits[i]->localPosition().y() );
451  }
452 
453  // merge clusters that are too close
454  // measure distance between final "running mean"
455  for(size_t NNN = 0; NNN < seeds.size(); ++NNN) {
456 
457  for(size_t MMM = NNN+1; MMM < seeds.size(); ++MMM) {
458  if(running_meanX[MMM] == 999999. || running_meanX[NNN] == 999999. ) {
459  LogTrace("CSCSegment|CSC") << "[CSCSegAlgoST::clusterHits] ALARM! Skipping used seeds, this should not happen - inform CSC DPG";
460  // std::cout<<"We should never see this line now!!!"<<std::endl;
461  continue; //skip seeds that have been used
462  }
463 
464  // calculate cut criteria for simple running mean distance cut:
465  //dXclus = fabs(running_meanX[NNN] - running_meanX[MMM]);
466  //dYclus = fabs(running_meanY[NNN] - running_meanY[MMM]);
467 
468  // calculate minmal distance between precluster boxes containing the hits:
469  if ( running_meanX[NNN] > running_meanX[MMM] ) dXclus_box = seed_minX[NNN] - seed_maxX[MMM];
470  else dXclus_box = seed_minX[MMM] - seed_maxX[NNN];
471  if ( running_meanY[NNN] > running_meanY[MMM] ) dYclus_box = seed_minY[NNN] - seed_maxY[MMM];
472  else dYclus_box = seed_minY[MMM] - seed_maxY[NNN];
473 
474 
475  if( dXclus_box < dXclusBoxMax && dYclus_box < dYclusBoxMax ) {
476  // merge clusters!
477  // merge by adding seed NNN to seed MMM and erasing seed NNN
478 
479  // calculate running mean for the merged seed:
480  running_meanX[MMM] = (running_meanX[NNN]*seeds[NNN].size() + running_meanX[MMM]*seeds[MMM].size()) / (seeds[NNN].size()+seeds[MMM].size());
481  running_meanY[MMM] = (running_meanY[NNN]*seeds[NNN].size() + running_meanY[MMM]*seeds[MMM].size()) / (seeds[NNN].size()+seeds[MMM].size());
482 
483  // update min/max X and Y for box containing the hits in the merged cluster:
484  if ( seed_minX[NNN] <= seed_minX[MMM] ) seed_minX[MMM] = seed_minX[NNN];
485  if ( seed_maxX[NNN] > seed_maxX[MMM] ) seed_maxX[MMM] = seed_maxX[NNN];
486  if ( seed_minY[NNN] <= seed_minY[MMM] ) seed_minY[MMM] = seed_minY[NNN];
487  if ( seed_maxY[NNN] > seed_maxY[MMM] ) seed_maxY[MMM] = seed_maxY[NNN];
488 
489  // add seed NNN to MMM (lower to larger number)
490  seeds[MMM].insert(seeds[MMM].end(),seeds[NNN].begin(),seeds[NNN].end());
491 
492  // mark seed NNN as used (at the moment just set running mean to 999999.)
493  running_meanX[NNN] = 999999.;
494  running_meanY[NNN] = 999999.;
495  // we have merged a seed (NNN) to the highter seed (MMM) - need to contimue to
496  // next seed (NNN+1)
497  break;
498  }
499 
500  }
501  }
502 
503  // hand over the final seeds to the output
504  // would be more elegant if we could do the above step with
505  // erasing the merged ones, rather than the
506  for(size_t NNN = 0; NNN < seeds.size(); ++NNN) {
507  if(running_meanX[NNN] == 999999.) continue; //skip seeds that have been marked as used up in merging
508  rechits_clusters.push_back(seeds[NNN]);
509  }
510 
511  //***************************************************************
512 
513  return rechits_clusters;
514 }
515 
516 
517 std::vector< std::vector<const CSCRecHit2D*> > CSCSegAlgoST::chainHits(const CSCChamber* aChamber, const ChamberHitContainer & rechits) {
518 
519  std::vector<ChamberHitContainer> rechits_chains; // this is a collection of groups of rechits
520 
521 
522  std::vector<const CSCRecHit2D*> temp;
523 
524  std::vector< ChamberHitContainer > seeds;
525 
526  std::vector <bool> usedCluster;
527 
528  // split rechits into subvectors and return vector of vectors:
529  // Loop over rechits
530  // Create one seed per hit
531  //std::cout<<" rechits.size() = "<<rechits.size()<<std::endl;
532  for(unsigned int i = 0; i < rechits.size(); ++i) {
533  temp.clear();
534  temp.push_back(rechits[i]);
535  seeds.push_back(temp);
536  usedCluster.push_back(false);
537  }
538  //@@ Only ME1/1A can have ganged strips so no need to test name
539  bool gangedME11a = false;
540  if ( ("ME1/a" == aChamber->specs()->chamberTypeName()) && aChamber->specs()->gangedStrips() ){
541  // if ( aChamber->specs()->gangedStrips() ){
542  gangedME11a = true;
543  }
544  // merge chains that are too close ("touch" each other)
545  for(size_t NNN = 0; NNN < seeds.size(); ++NNN) {
546  for(size_t MMM = NNN+1; MMM < seeds.size(); ++MMM) {
547  if(usedCluster[MMM] || usedCluster[NNN]){
548  continue;
549  }
550  // all is in the way we define "good";
551  // try not to "cluster" the hits but to "chain" them;
552  // it does the clustering but also does a better job
553  // for inclined tracks (not clustering them together;
554  // crossed tracks would be still clustered together)
555  // 22.12.09: In fact it is not much more different
556  // than the "clustering", we just introduce another
557  // variable in the game - Z. And it makes sense
558  // to re-introduce Y (or actually wire group mumber)
559  // in a similar way as for the strip number - see
560  // the code below.
561  bool goodToMerge = isGoodToMerge(gangedME11a, seeds[NNN], seeds[MMM]);
562  if(goodToMerge){
563  // merge chains!
564  // merge by adding seed NNN to seed MMM and erasing seed NNN
565 
566  // add seed NNN to MMM (lower to larger number)
567  seeds[MMM].insert(seeds[MMM].end(),seeds[NNN].begin(),seeds[NNN].end());
568 
569  // mark seed NNN as used
570  usedCluster[NNN] = true;
571  // we have merged a seed (NNN) to the highter seed (MMM) - need to contimue to
572  // next seed (NNN+1)
573  break;
574  }
575 
576  }
577  }
578 
579  // hand over the final seeds to the output
580  // would be more elegant if we could do the above step with
581  // erasing the merged ones, rather than the
582 
583  for(size_t NNN = 0; NNN < seeds.size(); ++NNN) {
584  if(usedCluster[NNN]) continue; //skip seeds that have been marked as used up in merging
585  rechits_chains.push_back(seeds[NNN]);
586  }
587 
588  //***************************************************************
589 
590  return rechits_chains;
591 }
592 
593 bool CSCSegAlgoST::isGoodToMerge(bool gangedME11a, ChamberHitContainer & newChain, ChamberHitContainer & oldChain) {
594  for(size_t iRH_new = 0;iRH_new<newChain.size();++iRH_new){
595  int layer_new = newChain[iRH_new]->cscDetId().layer()-1;
596  int middleStrip_new = newChain[iRH_new]->nStrips()/2;
597  int centralStrip_new = newChain[iRH_new]->channels(middleStrip_new);
598  int centralWire_new = newChain[iRH_new]->hitWire();
599  bool layerRequirementOK = false;
600  bool stripRequirementOK = false;
601  bool wireRequirementOK = false;
602  bool goodToMerge = false;
603  for(size_t iRH_old = 0;iRH_old<oldChain.size();++iRH_old){
604  int layer_old = oldChain[iRH_old]->cscDetId().layer()-1;
605  int middleStrip_old = oldChain[iRH_old]->nStrips()/2;
606  int centralStrip_old = oldChain[iRH_old]->channels(middleStrip_old);
607  int centralWire_old = oldChain[iRH_old]->hitWire();
608 
609  // to be chained, two hits need to be in neighbouring layers...
610  // or better allow few missing layers (upto 3 to avoid inefficiencies);
611  // however we'll not make an angle correction because it
612  // worsen the situation in some of the "regular" cases
613  // (not making the correction means that the conditions for
614  // forming a cluster are different if we have missing layers -
615  // this could affect events at the boundaries )
616  if(layer_new==layer_old+1 || layer_new==layer_old-1 ||
617  layer_new==layer_old+2 || layer_new==layer_old-2 ||
618  layer_new==layer_old+3 || layer_new==layer_old-3 ||
619  layer_new==layer_old+4 || layer_new==layer_old-4 ){
620  layerRequirementOK = true;
621  }
622  int allStrips = 48;
623  //to be chained, two hits need to be "close" in strip number (can do it in phi
624  // but it doesn't really matter); let "close" means upto 2 strips (3?) -
625  // this is more compared to what CLCT readout patterns allow
626  if(centralStrip_new==centralStrip_old ||
627  centralStrip_new==centralStrip_old+1 || centralStrip_new==centralStrip_old-1 ||
628  centralStrip_new==centralStrip_old+2 || centralStrip_new==centralStrip_old-2){
629  stripRequirementOK = true;
630  }
631  // same for wires (and ALCT patterns)
632  if(centralWire_new==centralWire_old ||
633  centralWire_new==centralWire_old+1 || centralWire_new==centralWire_old-1 ||
634  centralWire_new==centralWire_old+2 || centralWire_new==centralWire_old-2){
635  wireRequirementOK = true;
636  }
637 
638  if(gangedME11a){
639  if(centralStrip_new==centralStrip_old+1-allStrips || centralStrip_new==centralStrip_old-1-allStrips ||
640  centralStrip_new==centralStrip_old+2-allStrips || centralStrip_new==centralStrip_old-2-allStrips ||
641  centralStrip_new==centralStrip_old+1+allStrips || centralStrip_new==centralStrip_old-1+allStrips ||
642  centralStrip_new==centralStrip_old+2+allStrips || centralStrip_new==centralStrip_old-2+allStrips){
643  stripRequirementOK = true;
644  }
645  }
646  if(layerRequirementOK && stripRequirementOK && wireRequirementOK){
647  goodToMerge = true;
648  return goodToMerge;
649  }
650  }
651  }
652  return false;
653 }
654 
655 
656 
657 
658 double CSCSegAlgoST::theWeight(double coordinate_1, double coordinate_2, double coordinate_3, float layer_1, float layer_2, float layer_3) {
659  double sub_weight = 0;
660  sub_weight = fabs(
661  ( (coordinate_2 - coordinate_3) / (layer_2 - layer_3) ) -
662  ( (coordinate_1 - coordinate_2) / (layer_1 - layer_2) )
663  );
664  return sub_weight;
665 }
666 
667 /*
668  * This algorithm is based on the Minimum Spanning Tree (ST) approach
669  * for building endcap muon track segments out of the rechit's in a CSCChamber.
670  */
671 std::vector<CSCSegment> CSCSegAlgoST::buildSegments(const ChamberHitContainer& rechits) {
672 
673  // Clear buffer for segment vector
674  std::vector<CSCSegment> segmentInChamber;
675  segmentInChamber.clear(); // list of final segments
676 
677  // CSC Ring;
678  unsigned int thering = 999;
679  unsigned int thestation = 999;
680  //unsigned int thecham = 999;
681 
682  std::vector<int> hits_onLayerNumber(6);
683 
684  unsigned int UpperLimit = maxRecHitsInCluster;
685  if (int(rechits.size()) < minHitsPerSegment) return segmentInChamber;
686 
687  for(int iarray = 0; iarray <6; ++iarray) { // magic number 6: number of layers in CSC chamber - not gonna change :)
688  PAhits_onLayer[iarray].clear();
689  hits_onLayerNumber[iarray] = 0;
690  }
691 
692  chosen_Psegments.clear();
693  chosen_weight_A.clear();
694 
695  Psegments.clear();
696  Psegments_noLx.clear();
697  Psegments_noL1.clear();
698  Psegments_noL2.clear();
699  Psegments_noL3.clear();
700  Psegments_noL4.clear();
701  Psegments_noL5.clear();
702  Psegments_noL6.clear();
703 
704  Psegments_hits.clear();
705 
706  weight_A.clear();
707  weight_noLx_A.clear();
708  weight_noL1_A.clear();
709  weight_noL2_A.clear();
710  weight_noL3_A.clear();
711  weight_noL4_A.clear();
712  weight_noL5_A.clear();
713  weight_noL6_A.clear();
714 
715  weight_B.clear();
716  weight_noL1_B.clear();
717  weight_noL2_B.clear();
718  weight_noL3_B.clear();
719  weight_noL4_B.clear();
720  weight_noL5_B.clear();
721  weight_noL6_B.clear();
722 
723  curv_A.clear();
724  curv_noL1_A.clear();
725  curv_noL2_A.clear();
726  curv_noL3_A.clear();
727  curv_noL4_A.clear();
728  curv_noL5_A.clear();
729  curv_noL6_A.clear();
730 
731  // definition of middle layer for n-hit segment
732  int midlayer_pointer[6] = {0,0,2,3,3,4};
733 
734  // int n_layers_missed_tot = 0;
735  int n_layers_occupied_tot = 0;
736  int n_layers_processed = 0;
737 
738  float min_weight_A = 99999.9;
739  float min_weight_noLx_A = 99999.9;
740 
741  //float best_weight_B = -1.;
742  //float best_weight_noLx_B = -1.;
743 
744  //float best_curv_A = -1.;
745  //float best_curv_noLx_A = -1.;
746 
747  int best_pseg = -1;
748  int best_noLx_pseg = -1;
749  int best_Layer_noLx = -1;
750 
751  //************************************************************************;
752  //*** Start segment building *****************************************;
753  //************************************************************************;
754 
755  // Determine how many layers with hits we have
756  // Fill all hits into the layer hit container:
757 
758  // Have 2 standard arrays: one giving the number of hits per layer.
759  // The other the corresponding hits.
760 
761  // Loop all available hits, count hits per layer and fill the hits into array by layer
762  for(size_t M = 0; M < rechits.size(); ++M) {
763  // add hits to array per layer and count hits per layer:
764  hits_onLayerNumber[ rechits[M]->cscDetId().layer()-1 ] += 1;
765  if(hits_onLayerNumber[ rechits[M]->cscDetId().layer()-1 ] == 1 ) n_layers_occupied_tot += 1;
766  // add hits to vector in array
767  PAhits_onLayer[rechits[M]->cscDetId().layer()-1] .push_back(rechits[M]);
768  }
769 
770  // We have now counted the hits per layer and filled pointers to the hits into an array
771 
772  int tothits = 0;
773  int maxhits = 0;
774  int nexthits = 0;
775  int maxlayer = -1;
776  int nextlayer = -1;
777 
778  for(size_t i = 0; i< hits_onLayerNumber.size(); ++i){
779  //std::cout<<"We have "<<hits_onLayerNumber[i]<<" hits on layer "<<i+1<<std::endl;
780  tothits += hits_onLayerNumber[i];
781  if (hits_onLayerNumber[i] > maxhits) {
782  nextlayer = maxlayer;
783  nexthits = maxhits;
784  maxlayer = i;
785  maxhits = hits_onLayerNumber[i];
786  }
787  else if (hits_onLayerNumber[i] > nexthits) {
788  nextlayer = i;
789  nexthits = hits_onLayerNumber[i];
790  }
791  }
792 
793 
794  if (tothits > (int)UpperLimit) {
795  if (n_layers_occupied_tot > 4) {
796  tothits = tothits - hits_onLayerNumber[maxlayer];
797  n_layers_occupied_tot = n_layers_occupied_tot - 1;
798  PAhits_onLayer[maxlayer].clear();
799  hits_onLayerNumber[maxlayer] = 0;
800  }
801  }
802 
803  if (tothits > (int)UpperLimit) {
804  if (n_layers_occupied_tot > 4) {
805  tothits = tothits - hits_onLayerNumber[nextlayer];
806  n_layers_occupied_tot = n_layers_occupied_tot - 1;
807  PAhits_onLayer[nextlayer].clear();
808  hits_onLayerNumber[nextlayer] = 0;
809  }
810  }
811 
812  if (tothits > (int)UpperLimit){
813 
814  //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
815  // Showering muon - returns nothing if chi2 == -1 (see comment in SegAlgoShowering)
816  //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
817  if (useShowering) {
818  CSCSegment segShower = showering_->showerSeg(theChamber, rechits);
819 
820  // Make sure have at least 3 hits...
821  if ( segShower.nRecHits() < 3 ) return segmentInChamber;
822  if ( segShower.chi2() == -1 ) return segmentInChamber;
823 
824  segmentInChamber.push_back(segShower);
825  return segmentInChamber;
826 
827  } else{
828  LogTrace("CSCSegment|CSC") << "[CSCSegAlgoST::buildSegments] No. of rechits in the cluster/chamber > " << UpperLimit <<
829  " ... Segment finding in the cluster/chamber canceled!";
830  return segmentInChamber;
831  }
832  }
833 
834  // Find out which station, ring and chamber we are in
835  // Used to choose station/ring dependant y-weight cuts
836 
837  if( rechits.size() > 0 ) {
838  thering = rechits[0]->cscDetId().ring();
839  thestation = rechits[0]->cscDetId().station();
840  //thecham = rechits[0]->cscDetId().chamber();
841  }
842 
843  // std::cout<<"We are in Station/ring/chamber: "<<thestation <<" "<< thering<<" "<< thecham<<std::endl;
844 
845  // Cut-off parameter - don't reconstruct segments with less than X hits
846  if( n_layers_occupied_tot < minHitsPerSegment ) {
847  return segmentInChamber;
848  }
849 
850  // Start building all possible hit combinations:
851 
852  // loop over the six chamber layers and form segment candidates from the available hits:
853 
854  for(int layer = 0; layer < 6; ++layer) {
855 
856  // *****************************************************************
857  // *** Set missed layer counter here (not currently implemented) ***
858  // *****************************************************************
859  // if( PAhits_onLayer[layer].size() == 0 ) {
860  // n_layers_missed_tot += 1;
861  // }
862 
863  if( PAhits_onLayer[layer].size() > 0 ) {
864  n_layers_processed += 1;
865  }
866 
867  // Save the size of the protosegment before hits were added on the current layer
868  int orig_number_of_psegs = Psegments.size();
869  int orig_number_of_noL1_psegs = Psegments_noL1.size();
870  int orig_number_of_noL2_psegs = Psegments_noL2.size();
871  int orig_number_of_noL3_psegs = Psegments_noL3.size();
872  int orig_number_of_noL4_psegs = Psegments_noL4.size();
873  int orig_number_of_noL5_psegs = Psegments_noL5.size();
874  int orig_number_of_noL6_psegs = Psegments_noL6.size();
875 
876  // loop over the hits on the layer and initiate protosegments or add hits to protosegments
877  for(int hit = 0; hit < int(PAhits_onLayer[layer].size()); ++hit) { // loop all hits on the Layer number "layer"
878 
879  // create protosegments from all hits on the first layer with hits
880  if( orig_number_of_psegs == 0 ) { // would be faster to turn this around - ask for "orig_number_of_psegs != 0"
881 
882  Psegments_hits.push_back(PAhits_onLayer[layer][hit]);
883 
884  Psegments.push_back(Psegments_hits);
885  Psegments_noL6.push_back(Psegments_hits);
886  Psegments_noL5.push_back(Psegments_hits);
887  Psegments_noL4.push_back(Psegments_hits);
888  Psegments_noL3.push_back(Psegments_hits);
889  Psegments_noL2.push_back(Psegments_hits);
890 
891  // Initialize weights corresponding to this segment for first hit (with 0)
892 
893  curv_A.push_back(0.0);
894  curv_noL6_A.push_back(0.0);
895  curv_noL5_A.push_back(0.0);
896  curv_noL4_A.push_back(0.0);
897  curv_noL3_A.push_back(0.0);
898  curv_noL2_A.push_back(0.0);
899 
900  weight_A.push_back(0.0);
901  weight_noL6_A.push_back(0.0);
902  weight_noL5_A.push_back(0.0);
903  weight_noL4_A.push_back(0.0);
904  weight_noL3_A.push_back(0.0);
905  weight_noL2_A.push_back(0.0);
906 
907  weight_B.push_back(0.0);
908  weight_noL6_B.push_back(0.0);
909  weight_noL5_B.push_back(0.0);
910  weight_noL4_B.push_back(0.0);
911  weight_noL3_B.push_back(0.0);
912  weight_noL2_B.push_back(0.0);
913 
914  // reset array for next hit on next layer
915  Psegments_hits .clear();
916  }
917  else {
918  if( orig_number_of_noL1_psegs == 0 ) {
919 
920  Psegments_hits.push_back(PAhits_onLayer[layer][hit]);
921 
922  Psegments_noL1.push_back(Psegments_hits);
923 
924  // Initialize weight corresponding to this segment for first hit (with 0)
925 
926  curv_noL1_A.push_back(0.0);
927 
928  weight_noL1_A.push_back(0.0);
929 
930  weight_noL1_B.push_back(0.0);
931 
932  // reset array for next hit on next layer
933  Psegments_hits .clear();
934 
935  }
936 
937  // loop over the protosegments and create a new protosegments for each hit-1 on this layer
938 
939  for( int pseg = 0; pseg < orig_number_of_psegs; ++pseg ) {
940 
941  int pseg_pos = (pseg)+((hit)*orig_number_of_psegs);
942  int pseg_noL1_pos = (pseg)+((hit)*orig_number_of_noL1_psegs);
943  int pseg_noL2_pos = (pseg)+((hit)*orig_number_of_noL2_psegs);
944  int pseg_noL3_pos = (pseg)+((hit)*orig_number_of_noL3_psegs);
945  int pseg_noL4_pos = (pseg)+((hit)*orig_number_of_noL4_psegs);
946  int pseg_noL5_pos = (pseg)+((hit)*orig_number_of_noL5_psegs);
947  int pseg_noL6_pos = (pseg)+((hit)*orig_number_of_noL6_psegs);
948 
949  // - Loop all psegs.
950  // - If not last hit, clone existing protosegments (PAhits_onLayer[layer].size()-1) times
951  // - then add the new hits
952 
953  if( ! (hit == int(PAhits_onLayer[layer].size()-1)) ) { // not the last hit - prepare (copy) new protosegments for the following hits
954  // clone psegs (to add next hits or last hit on layer):
955 
956  Psegments.push_back(Psegments[ pseg_pos ]);
957  if (n_layers_processed != 2 && pseg < orig_number_of_noL1_psegs) Psegments_noL1.push_back(Psegments_noL1[ pseg_noL1_pos ]);
958  if (n_layers_processed != 2 && pseg < orig_number_of_noL2_psegs) Psegments_noL2.push_back(Psegments_noL2[ pseg_noL2_pos ]);
959  if (n_layers_processed != 3 && pseg < orig_number_of_noL3_psegs) Psegments_noL3.push_back(Psegments_noL3[ pseg_noL3_pos ]);
960  if (n_layers_processed != 4 && pseg < orig_number_of_noL4_psegs) Psegments_noL4.push_back(Psegments_noL4[ pseg_noL4_pos ]);
961  if (n_layers_processed != 5 && pseg < orig_number_of_noL5_psegs) Psegments_noL5.push_back(Psegments_noL5[ pseg_noL5_pos ]);
962  if (n_layers_processed != 6 && pseg < orig_number_of_noL6_psegs) Psegments_noL6.push_back(Psegments_noL6[ pseg_noL6_pos ]);
963  // clone weight corresponding to this segment too
964  weight_A.push_back(weight_A[ pseg_pos ]);
965  if (n_layers_processed != 2 && pseg < orig_number_of_noL1_psegs) weight_noL1_A.push_back(weight_noL1_A[ pseg_noL1_pos ]);
966  if (n_layers_processed != 2 && pseg < orig_number_of_noL2_psegs) weight_noL2_A.push_back(weight_noL2_A[ pseg_noL2_pos ]);
967  if (n_layers_processed != 3 && pseg < orig_number_of_noL3_psegs) weight_noL3_A.push_back(weight_noL3_A[ pseg_noL3_pos ]);
968  if (n_layers_processed != 4 && pseg < orig_number_of_noL4_psegs) weight_noL4_A.push_back(weight_noL4_A[ pseg_noL4_pos ]);
969  if (n_layers_processed != 5 && pseg < orig_number_of_noL5_psegs) weight_noL5_A.push_back(weight_noL5_A[ pseg_noL5_pos ]);
970  if (n_layers_processed != 6 && pseg < orig_number_of_noL6_psegs) weight_noL6_A.push_back(weight_noL6_A[ pseg_noL6_pos ]);
971  // clone curvature variable corresponding to this segment too
972  curv_A.push_back(curv_A[ pseg_pos ]);
973  if (n_layers_processed != 2 && pseg < orig_number_of_noL1_psegs) curv_noL1_A.push_back(curv_noL1_A[ pseg_noL1_pos ]);
974  if (n_layers_processed != 2 && pseg < orig_number_of_noL2_psegs) curv_noL2_A.push_back(curv_noL2_A[ pseg_noL2_pos ]);
975  if (n_layers_processed != 3 && pseg < orig_number_of_noL3_psegs) curv_noL3_A.push_back(curv_noL3_A[ pseg_noL3_pos ]);
976  if (n_layers_processed != 4 && pseg < orig_number_of_noL4_psegs) curv_noL4_A.push_back(curv_noL4_A[ pseg_noL4_pos ]);
977  if (n_layers_processed != 5 && pseg < orig_number_of_noL5_psegs) curv_noL5_A.push_back(curv_noL5_A[ pseg_noL5_pos ]);
978  if (n_layers_processed != 6 && pseg < orig_number_of_noL6_psegs) curv_noL6_A.push_back(curv_noL6_A[ pseg_noL6_pos ]);
979  // clone "y"-weight corresponding to this segment too
980  weight_B.push_back(weight_B[ pseg_pos ]);
981  if (n_layers_processed != 2 && pseg < orig_number_of_noL1_psegs) weight_noL1_B.push_back(weight_noL1_B[ pseg_noL1_pos ]);
982  if (n_layers_processed != 2 && pseg < orig_number_of_noL2_psegs) weight_noL2_B.push_back(weight_noL2_B[ pseg_noL2_pos ]);
983  if (n_layers_processed != 3 && pseg < orig_number_of_noL3_psegs) weight_noL3_B.push_back(weight_noL3_B[ pseg_noL3_pos ]);
984  if (n_layers_processed != 4 && pseg < orig_number_of_noL4_psegs) weight_noL4_B.push_back(weight_noL4_B[ pseg_noL4_pos ]);
985  if (n_layers_processed != 5 && pseg < orig_number_of_noL5_psegs) weight_noL5_B.push_back(weight_noL5_B[ pseg_noL5_pos ]);
986  if (n_layers_processed != 6 && pseg < orig_number_of_noL6_psegs) weight_noL6_B.push_back(weight_noL6_B[ pseg_noL6_pos ]);
987  }
988  // add hits to original pseg:
989  Psegments[ pseg_pos ].push_back(PAhits_onLayer[ layer ][ hit ]);
990  if (n_layers_processed != 2 && pseg < orig_number_of_noL1_psegs) Psegments_noL1[ pseg_noL1_pos ].push_back(PAhits_onLayer[ layer ][ hit ]);
991  if (n_layers_processed != 2 && pseg < orig_number_of_noL2_psegs) Psegments_noL2[ pseg_noL2_pos ].push_back(PAhits_onLayer[ layer ][ hit ]);
992  if (n_layers_processed != 3 && pseg < orig_number_of_noL3_psegs) Psegments_noL3[ pseg_noL3_pos ].push_back(PAhits_onLayer[ layer ][ hit ]);
993  if (n_layers_processed != 4 && pseg < orig_number_of_noL4_psegs) Psegments_noL4[ pseg_noL4_pos ].push_back(PAhits_onLayer[ layer ][ hit ]);
994  if (n_layers_processed != 5 && pseg < orig_number_of_noL5_psegs) Psegments_noL5[ pseg_noL5_pos ].push_back(PAhits_onLayer[ layer ][ hit ]);
995  if (n_layers_processed != 6 && pseg < orig_number_of_noL6_psegs) Psegments_noL6[ pseg_noL6_pos ].push_back(PAhits_onLayer[ layer ][ hit ]);
996 
997  // calculate/update the weight (only for >2 hits on psegment):
998 
999  if( Psegments[ pseg_pos ].size() > 2 ) {
1000 
1001  // 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,
1002  // divided by the distance of the corresponding hits. Please refer to twiki page XXXX or CMS Note YYY (and use layer_distance)
1003 
1004  weight_A[ pseg_pos ] += theWeight(
1005  (*(Psegments[ pseg_pos ].end()-1 ))->localPosition().x(),
1006  (*(Psegments[ pseg_pos ].end()-2 ))->localPosition().x(),
1007  (*(Psegments[ pseg_pos ].end()-3 ))->localPosition().x(),
1008  float((*(Psegments[ pseg_pos ].end()-1))->cscDetId().layer()),
1009  float((*(Psegments[ pseg_pos ].end()-2))->cscDetId().layer()),
1010  float((*(Psegments[ pseg_pos ].end()-3))->cscDetId().layer())
1011  );
1012 
1013  weight_B[ pseg_pos ] += theWeight(
1014  (*(Psegments[ pseg_pos ].end()-1 ))->localPosition().y(),
1015  (*(Psegments[ pseg_pos ].end()-2 ))->localPosition().y(),
1016  (*(Psegments[ pseg_pos ].end()-3 ))->localPosition().y(),
1017  float((*(Psegments[ pseg_pos ].end()-1))->cscDetId().layer()),
1018  float((*(Psegments[ pseg_pos ].end()-2))->cscDetId().layer()),
1019  float((*(Psegments[ pseg_pos ].end()-3))->cscDetId().layer())
1020  );
1021 
1022  // if we have picked up the last hit go looking for pseg with the lowest (and second lowest?) weight
1023 
1024  if(int(Psegments[ pseg_pos ].size()) == n_layers_occupied_tot) {
1025 
1026  curv_A[ pseg_pos ] += theWeight(
1027  (*(Psegments[ pseg_pos ].end()-1 ))->localPosition().x(),
1028  (*(Psegments[ pseg_pos ].end()-midlayer_pointer[n_layers_occupied_tot-1] ))->localPosition().x(),
1029  (*(Psegments[ pseg_pos ].end()-n_layers_occupied_tot ))->localPosition().x(),
1030  float((*(Psegments[ pseg_pos ].end()-1))->cscDetId().layer()),
1031  float((*(Psegments[ pseg_pos ].end()-midlayer_pointer[n_layers_occupied_tot-1] ))->cscDetId().layer()),
1032  float((*(Psegments[ pseg_pos ].end()-n_layers_occupied_tot ))->cscDetId().layer())
1033  );
1034 
1035  if (curv_A[ pseg_pos ] > curvePenaltyThreshold) weight_A[ pseg_pos ] = weight_A[ pseg_pos ] * curvePenalty;
1036 
1037  if (weight_B[ pseg_pos ] > a_yweightPenaltyThreshold[thestation][thering]) weight_A[ pseg_pos ] = weight_A[ pseg_pos ] * yweightPenalty;
1038 
1039  if (weight_A[ pseg_pos ] < min_weight_A ) {
1040  min_weight_A = weight_A[ pseg_pos ];
1041  //best_weight_B = weight_B[ pseg_pos ];
1042  //best_curv_A = curv_A[ pseg_pos ];
1043  best_pseg = pseg_pos ;
1044  }
1045 
1046  }
1047 
1048  // alternative: fill map with weight and pseg (which is already ordered)? Seems a very good tool to go looking for segments from.
1049  // As I understand, the segments would be inserted according to their weight, so the list would "automatically" be sorted.
1050 
1051  }
1052 
1053  if ( n_layers_occupied_tot > 3 ) {
1054  if (pseg < orig_number_of_noL1_psegs && (n_layers_processed != 2)) {
1055  if(( Psegments_noL1[ pseg_noL1_pos ].size() > 2 ) ) {
1056 
1057  // 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,
1058  // divided by the distance of the corresponding hits. Please refer to twiki page XXXX or CMS Note YYY (and use layer_distance)
1059 
1060  weight_noL1_A[ pseg_noL1_pos ] += theWeight(
1061  (*(Psegments_noL1[ pseg_noL1_pos ].end()-1 ))->localPosition().x(),
1062  (*(Psegments_noL1[ pseg_noL1_pos ].end()-2 ))->localPosition().x(),
1063  (*(Psegments_noL1[ pseg_noL1_pos ].end()-3 ))->localPosition().x(),
1064  float((*(Psegments_noL1[ pseg_noL1_pos ].end()-1))->cscDetId().layer()),
1065  float((*(Psegments_noL1[ pseg_noL1_pos ].end()-2))->cscDetId().layer()),
1066  float((*(Psegments_noL1[ pseg_noL1_pos ].end()-3))->cscDetId().layer())
1067  );
1068 
1069  weight_noL1_B[ pseg_noL1_pos ] += theWeight(
1070  (*(Psegments_noL1[ pseg_noL1_pos ].end()-1 ))->localPosition().y(),
1071  (*(Psegments_noL1[ pseg_noL1_pos ].end()-2 ))->localPosition().y(),
1072  (*(Psegments_noL1[ pseg_noL1_pos ].end()-3 ))->localPosition().y(),
1073  float((*(Psegments_noL1[ pseg_noL1_pos ].end()-1))->cscDetId().layer()),
1074  float((*(Psegments_noL1[ pseg_noL1_pos ].end()-2))->cscDetId().layer()),
1075  float((*(Psegments_noL1[ pseg_noL1_pos ].end()-3))->cscDetId().layer())
1076  );
1077 
1078  //if we have picked up the last hit go looking for pseg with the lowest (and second lowest?) weight
1079 
1080  if(int(Psegments_noL1[ pseg_noL1_pos ].size()) == n_layers_occupied_tot -1 ) {
1081 
1082  curv_noL1_A[ pseg_noL1_pos ] += theWeight(
1083  (*(Psegments_noL1[ pseg_noL1_pos ].end()-1 ))->localPosition().x(),
1084  (*(Psegments_noL1[ pseg_noL1_pos ].end()-midlayer_pointer[n_layers_occupied_tot-2] ))->localPosition().x(),
1085  (*(Psegments_noL1[ pseg_noL1_pos ].end()-(n_layers_occupied_tot-1) ))->localPosition().x(),
1086  float((*(Psegments_noL1[ pseg_noL1_pos ].end()-1 ))->cscDetId().layer()),
1087  float((*(Psegments_noL1[ pseg_noL1_pos ].end()-midlayer_pointer[n_layers_occupied_tot-2] ))->cscDetId().layer()),
1088  float((*(Psegments_noL1[ pseg_noL1_pos ].end()-(n_layers_occupied_tot-1) ))->cscDetId().layer())
1089  );
1090 
1091  if (curv_noL1_A[ pseg_noL1_pos ] > curvePenaltyThreshold) weight_noL1_A[ pseg_noL1_pos ] = weight_noL1_A[ pseg_noL1_pos ] * curvePenalty;
1092 
1093  if (weight_noL1_B[ pseg_noL1_pos ] > a_yweightPenaltyThreshold[thestation][thering])
1094  weight_noL1_A[ pseg_noL1_pos ] = weight_noL1_A[ pseg_noL1_pos ] * yweightPenalty;
1095 
1096  if (weight_noL1_A[ pseg_noL1_pos ] < min_weight_noLx_A ) {
1097  min_weight_noLx_A = weight_noL1_A[ pseg_noL1_pos ];
1098  //best_weight_noLx_B = weight_noL1_B[ pseg_noL1_pos ];
1099  //best_curv_noLx_A = curv_noL1_A[ pseg_noL1_pos ];
1100  best_noLx_pseg = pseg_noL1_pos;
1101  best_Layer_noLx = 1;
1102  }
1103 
1104  }
1105 
1106  // alternative: fill map with weight and pseg (which is already ordered)? Seems a very good tool to go looking for segments from.
1107  // As I understand, the segments would be inserted according to their weight, so the list would "automatically" be sorted.
1108 
1109  }
1110  }
1111  }
1112 
1113  if ( n_layers_occupied_tot > 3 ) {
1114  if (pseg < orig_number_of_noL2_psegs && ( n_layers_processed != 2 )) {
1115  if(( Psegments_noL2[ pseg_noL2_pos ].size() > 2 )) {
1116 
1117  // 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,
1118  // divided by the distance of the corresponding hits. Please refer to twiki page XXXX or CMS Note YYY (and use layer_distance)
1119 
1120  weight_noL2_A[ pseg_noL2_pos ] += theWeight(
1121  (*(Psegments_noL2[ pseg_noL2_pos ].end()-1 ))->localPosition().x(),
1122  (*(Psegments_noL2[ pseg_noL2_pos ].end()-2 ))->localPosition().x(),
1123  (*(Psegments_noL2[ pseg_noL2_pos ].end()-3 ))->localPosition().x(),
1124  float((*(Psegments_noL2[ pseg_noL2_pos ].end()-1))->cscDetId().layer()),
1125  float((*(Psegments_noL2[ pseg_noL2_pos ].end()-2))->cscDetId().layer()),
1126  float((*(Psegments_noL2[ pseg_noL2_pos ].end()-3))->cscDetId().layer())
1127  );
1128 
1129  weight_noL2_B[ pseg_noL2_pos ] += theWeight(
1130  (*(Psegments_noL2[ pseg_noL2_pos ].end()-1 ))->localPosition().y(),
1131  (*(Psegments_noL2[ pseg_noL2_pos ].end()-2 ))->localPosition().y(),
1132  (*(Psegments_noL2[ pseg_noL2_pos ].end()-3 ))->localPosition().y(),
1133  float((*(Psegments_noL2[ pseg_noL2_pos ].end()-1))->cscDetId().layer()),
1134  float((*(Psegments_noL2[ pseg_noL2_pos ].end()-2))->cscDetId().layer()),
1135  float((*(Psegments_noL2[ pseg_noL2_pos ].end()-3))->cscDetId().layer())
1136  );
1137 
1138  //if we have picked up the last hit go looking for pseg with the lowest (and second lowest?) weight
1139 
1140  if(int(Psegments_noL2[ pseg_noL2_pos ].size()) == n_layers_occupied_tot -1 ) {
1141 
1142  curv_noL2_A[ pseg_noL2_pos ] += theWeight(
1143  (*(Psegments_noL2[ pseg_noL2_pos ].end()-1 ))->localPosition().x(),
1144  (*(Psegments_noL2[ pseg_noL2_pos ].end()-midlayer_pointer[n_layers_occupied_tot-2] ))->localPosition().x(),
1145  (*(Psegments_noL2[ pseg_noL2_pos ].end()-(n_layers_occupied_tot-1) ))->localPosition().x(),
1146  float((*(Psegments_noL2[ pseg_noL2_pos ].end()-1 ))->cscDetId().layer()),
1147  float((*(Psegments_noL2[ pseg_noL2_pos ].end()-midlayer_pointer[n_layers_occupied_tot-2] ))->cscDetId().layer()),
1148  float((*(Psegments_noL2[ pseg_noL2_pos ].end()-(n_layers_occupied_tot-1) ))->cscDetId().layer())
1149  );
1150 
1151  if (curv_noL2_A[ pseg_noL2_pos ] > curvePenaltyThreshold) weight_noL2_A[ pseg_noL2_pos ] = weight_noL2_A[ pseg_noL2_pos ] * curvePenalty;
1152 
1153  if (weight_noL2_B[ pseg_noL2_pos ] > a_yweightPenaltyThreshold[thestation][thering])
1154  weight_noL2_A[ pseg_noL2_pos ] = weight_noL2_A[ pseg_noL2_pos ] * yweightPenalty;
1155 
1156  if (weight_noL2_A[ pseg_noL2_pos ] < min_weight_noLx_A ) {
1157  min_weight_noLx_A = weight_noL2_A[ pseg_noL2_pos ];
1158  //best_weight_noLx_B = weight_noL2_B[ pseg_noL2_pos ];
1159  //best_curv_noLx_A = curv_noL2_A[ pseg_noL2_pos ];
1160  best_noLx_pseg = pseg_noL2_pos;
1161  best_Layer_noLx = 2;
1162  }
1163 
1164  }
1165 
1166  // alternative: fill map with weight and pseg (which is already ordered)? Seems a very good tool to go looking for segments from.
1167  // As I understand, the segments would be inserted according to their weight, so the list would "automatically" be sorted.
1168 
1169  }
1170  }
1171  }
1172 
1173  if ( n_layers_occupied_tot > 3 ) {
1174  if (pseg < orig_number_of_noL3_psegs && ( n_layers_processed != 3 )) {
1175  if(( Psegments_noL3[ pseg_noL3_pos ].size() > 2 )) {
1176 
1177  // 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,
1178  // divided by the distance of the corresponding hits. Please refer to twiki page XXXX or CMS Note YYY (and use layer_distance)
1179 
1180  weight_noL3_A[ pseg_noL3_pos ] += theWeight(
1181  (*(Psegments_noL3[ pseg_noL3_pos ].end()-1 ))->localPosition().x(),
1182  (*(Psegments_noL3[ pseg_noL3_pos ].end()-2 ))->localPosition().x(),
1183  (*(Psegments_noL3[ pseg_noL3_pos ].end()-3 ))->localPosition().x(),
1184  float((*(Psegments_noL3[ pseg_noL3_pos ].end()-1))->cscDetId().layer()),
1185  float((*(Psegments_noL3[ pseg_noL3_pos ].end()-2))->cscDetId().layer()),
1186  float((*(Psegments_noL3[ pseg_noL3_pos ].end()-3))->cscDetId().layer())
1187  );
1188 
1189  weight_noL3_B[ pseg_noL3_pos ] += theWeight(
1190  (*(Psegments_noL3[ pseg_noL3_pos ].end()-1 ))->localPosition().y(),
1191  (*(Psegments_noL3[ pseg_noL3_pos ].end()-2 ))->localPosition().y(),
1192  (*(Psegments_noL3[ pseg_noL3_pos ].end()-3 ))->localPosition().y(),
1193  float((*(Psegments_noL3[ pseg_noL3_pos ].end()-1))->cscDetId().layer()),
1194  float((*(Psegments_noL3[ pseg_noL3_pos ].end()-2))->cscDetId().layer()),
1195  float((*(Psegments_noL3[ pseg_noL3_pos ].end()-3))->cscDetId().layer())
1196  );
1197 
1198  //if we have picked up the last hit go looking for pseg with the lowest (and second lowest?) weight
1199 
1200  if(int(Psegments_noL3[ pseg_noL3_pos ].size()) == n_layers_occupied_tot -1 ) {
1201 
1202  curv_noL3_A[ pseg_noL3_pos ] += theWeight(
1203  (*(Psegments_noL3[ pseg_noL3_pos ].end()-1 ))->localPosition().x(),
1204  (*(Psegments_noL3[ pseg_noL3_pos ].end()-midlayer_pointer[n_layers_occupied_tot-2] ))->localPosition().x(),
1205  (*(Psegments_noL3[ pseg_noL3_pos ].end()-(n_layers_occupied_tot-1) ))->localPosition().x(),
1206  float((*(Psegments_noL3[ pseg_noL3_pos ].end()-1 ))->cscDetId().layer()),
1207  float((*(Psegments_noL3[ pseg_noL3_pos ].end()-midlayer_pointer[n_layers_occupied_tot-2] ))->cscDetId().layer()),
1208  float((*(Psegments_noL3[ pseg_noL3_pos ].end()-(n_layers_occupied_tot-1) ))->cscDetId().layer())
1209  );
1210 
1211  if (curv_noL3_A[ pseg_noL3_pos ] > curvePenaltyThreshold) weight_noL3_A[ pseg_noL3_pos ] = weight_noL3_A[ pseg_noL3_pos ] * curvePenalty;
1212 
1213  if (weight_noL3_B[ pseg_noL3_pos ] > a_yweightPenaltyThreshold[thestation][thering])
1214  weight_noL3_A[ pseg_noL3_pos ] = weight_noL3_A[ pseg_noL3_pos ] * yweightPenalty;
1215 
1216  if (weight_noL3_A[ pseg_noL3_pos ] < min_weight_noLx_A ) {
1217  min_weight_noLx_A = weight_noL3_A[ pseg_noL3_pos ];
1218  //best_weight_noLx_B = weight_noL3_B[ pseg_noL3_pos ];
1219  //best_curv_noLx_A = curv_noL3_A[ pseg_noL3_pos ];
1220  best_noLx_pseg = pseg_noL3_pos;
1221  best_Layer_noLx = 3;
1222  }
1223 
1224  }
1225 
1226  // alternative: fill map with weight and pseg (which is already ordered)? Seems a very good tool to go looking for segments from.
1227  // As I understand, the segments would be inserted according to their weight, so the list would "automatically" be sorted.
1228 
1229  }
1230  }
1231  }
1232 
1233  if ( n_layers_occupied_tot > 3 ) {
1234  if (pseg < orig_number_of_noL4_psegs && ( n_layers_processed != 4 )) {
1235  if(( Psegments_noL4[ pseg_noL4_pos ].size() > 2 )) {
1236 
1237  // 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,
1238  // divided by the distance of the corresponding hits. Please refer to twiki page XXXX or CMS Note YYY (and use layer_distance)
1239 
1240  weight_noL4_A[ pseg_noL4_pos ] += theWeight(
1241  (*(Psegments_noL4[ pseg_noL4_pos ].end()-1 ))->localPosition().x(),
1242  (*(Psegments_noL4[ pseg_noL4_pos ].end()-2 ))->localPosition().x(),
1243  (*(Psegments_noL4[ pseg_noL4_pos ].end()-3 ))->localPosition().x(),
1244  float((*(Psegments_noL4[ pseg_noL4_pos ].end()-1))->cscDetId().layer()),
1245  float((*(Psegments_noL4[ pseg_noL4_pos ].end()-2))->cscDetId().layer()),
1246  float((*(Psegments_noL4[ pseg_noL4_pos ].end()-3))->cscDetId().layer())
1247  );
1248 
1249  weight_noL4_B[ pseg_noL4_pos ] += theWeight(
1250  (*(Psegments_noL4[ pseg_noL4_pos ].end()-1 ))->localPosition().y(),
1251  (*(Psegments_noL4[ pseg_noL4_pos ].end()-2 ))->localPosition().y(),
1252  (*(Psegments_noL4[ pseg_noL4_pos ].end()-3 ))->localPosition().y(),
1253  float((*(Psegments_noL4[ pseg_noL4_pos ].end()-1))->cscDetId().layer()),
1254  float((*(Psegments_noL4[ pseg_noL4_pos ].end()-2))->cscDetId().layer()),
1255  float((*(Psegments_noL4[ pseg_noL4_pos ].end()-3))->cscDetId().layer())
1256  );
1257 
1258  //if we have picked up the last hit go looking for pseg with the lowest (and second lowest?) weight
1259 
1260  if(int(Psegments_noL4[ pseg_noL4_pos ].size()) == n_layers_occupied_tot -1 ) {
1261 
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] ))->localPosition().x(),
1265  (*(Psegments_noL4[ pseg_noL4_pos ].end()-(n_layers_occupied_tot-1) ))->localPosition().x(),
1266  float((*(Psegments_noL4[ pseg_noL4_pos ].end()-1 ))->cscDetId().layer()),
1267  float((*(Psegments_noL4[ pseg_noL4_pos ].end()-midlayer_pointer[n_layers_occupied_tot-2] ))->cscDetId().layer()),
1268  float((*(Psegments_noL4[ pseg_noL4_pos ].end()-(n_layers_occupied_tot-1) ))->cscDetId().layer())
1269  );
1270 
1271  if (curv_noL4_A[ pseg_noL4_pos ] > curvePenaltyThreshold) weight_noL4_A[ pseg_noL4_pos ] = weight_noL4_A[ pseg_noL4_pos ] * curvePenalty;
1272 
1273  if (weight_noL4_B[ pseg_noL4_pos ] > a_yweightPenaltyThreshold[thestation][thering])
1274  weight_noL4_A[ pseg_noL4_pos ] = weight_noL4_A[ pseg_noL4_pos ] * yweightPenalty;
1275 
1276  if (weight_noL4_A[ pseg_noL4_pos ] < min_weight_noLx_A ) {
1277  min_weight_noLx_A = weight_noL4_A[ pseg_noL4_pos ];
1278  //best_weight_noLx_B = weight_noL4_B[ pseg_noL4_pos ];
1279  //best_curv_noLx_A = curv_noL4_A[ pseg_noL4_pos ];
1280  best_noLx_pseg = pseg_noL4_pos;
1281  best_Layer_noLx = 4;
1282  }
1283 
1284  }
1285 
1286  // alternative: fill map with weight and pseg (which is already ordered)? Seems a very good tool to go looking for segments from.
1287  // As I understand, the segments would be inserted according to their weight, so the list would "automatically" be sorted.
1288 
1289  }
1290  }
1291  }
1292 
1293  if ( n_layers_occupied_tot > 4 ) {
1294  if (pseg < orig_number_of_noL5_psegs && ( n_layers_processed != 5 )) {
1295  if(( Psegments_noL5[ pseg_noL5_pos ].size() > 2 )){
1296 
1297  // 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,
1298  // divided by the distance of the corresponding hits. Please refer to twiki page XXXX or CMS Note YYY (and use layer_distance)
1299 
1300  weight_noL5_A[ pseg_noL5_pos ] += theWeight(
1301  (*(Psegments_noL5[ pseg_noL5_pos ].end()-1 ))->localPosition().x(),
1302  (*(Psegments_noL5[ pseg_noL5_pos ].end()-2 ))->localPosition().x(),
1303  (*(Psegments_noL5[ pseg_noL5_pos ].end()-3 ))->localPosition().x(),
1304  float((*(Psegments_noL5[ pseg_noL5_pos ].end()-1))->cscDetId().layer()),
1305  float((*(Psegments_noL5[ pseg_noL5_pos ].end()-2))->cscDetId().layer()),
1306  float((*(Psegments_noL5[ pseg_noL5_pos ].end()-3))->cscDetId().layer())
1307  );
1308 
1309  weight_noL5_B[ pseg_noL5_pos ] += theWeight(
1310  (*(Psegments_noL5[ pseg_noL5_pos ].end()-1 ))->localPosition().y(),
1311  (*(Psegments_noL5[ pseg_noL5_pos ].end()-2 ))->localPosition().y(),
1312  (*(Psegments_noL5[ pseg_noL5_pos ].end()-3 ))->localPosition().y(),
1313  float((*(Psegments_noL5[ pseg_noL5_pos ].end()-1))->cscDetId().layer()),
1314  float((*(Psegments_noL5[ pseg_noL5_pos ].end()-2))->cscDetId().layer()),
1315  float((*(Psegments_noL5[ pseg_noL5_pos ].end()-3))->cscDetId().layer())
1316  );
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 
1322  curv_noL5_A[ pseg_noL5_pos ] += theWeight(
1323  (*(Psegments_noL5[ pseg_noL5_pos ].end()-1 ))->localPosition().x(),
1324  (*(Psegments_noL5[ pseg_noL5_pos ].end()-midlayer_pointer[n_layers_occupied_tot-2] ))->localPosition().x(),
1325  (*(Psegments_noL5[ pseg_noL5_pos ].end()-(n_layers_occupied_tot-1) ))->localPosition().x(),
1326  float((*(Psegments_noL5[ pseg_noL5_pos ].end()-1 ))->cscDetId().layer()),
1327  float((*(Psegments_noL5[ pseg_noL5_pos ].end()-midlayer_pointer[n_layers_occupied_tot-2] ))->cscDetId().layer()),
1328  float((*(Psegments_noL5[ pseg_noL5_pos ].end()-(n_layers_occupied_tot-1) ))->cscDetId().layer())
1329  );
1330 
1331  if (curv_noL5_A[ pseg_noL5_pos ] > curvePenaltyThreshold) weight_noL5_A[ pseg_noL5_pos ] = weight_noL5_A[ pseg_noL5_pos ] * curvePenalty;
1332 
1333  if (weight_noL5_B[ pseg_noL5_pos ] > a_yweightPenaltyThreshold[thestation][thering])
1334  weight_noL5_A[ pseg_noL5_pos ] = weight_noL5_A[ pseg_noL5_pos ] * yweightPenalty;
1335 
1336  if (weight_noL5_A[ pseg_noL5_pos ] < min_weight_noLx_A ) {
1337  min_weight_noLx_A = weight_noL5_A[ pseg_noL5_pos ];
1338  //best_weight_noLx_B = weight_noL5_B[ pseg_noL5_pos ];
1339  //best_curv_noLx_A = curv_noL5_A[ pseg_noL5_pos ];
1340  best_noLx_pseg = pseg_noL5_pos;
1341  best_Layer_noLx = 5;
1342  }
1343 
1344  }
1345 
1346  // alternative: fill map with weight and pseg (which is already ordered)? Seems a very good tool to go looking for segments from.
1347  // As I understand, the segments would be inserted according to their weight, so the list would "automatically" be sorted.
1348 
1349  }
1350  }
1351  }
1352 
1353  if ( n_layers_occupied_tot > 5 ) {
1354  if (pseg < orig_number_of_noL6_psegs && ( n_layers_processed != 6 )) {
1355  if(( Psegments_noL6[ pseg_noL6_pos ].size() > 2 )){
1356 
1357  // 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,
1358  // divided by the distance of the corresponding hits. Please refer to twiki page XXXX or CMS Note YYY (and use layer_distance)
1359 
1360  weight_noL6_A[ pseg_noL6_pos ] += theWeight(
1361  (*(Psegments_noL6[ pseg_noL6_pos ].end()-1 ))->localPosition().x(),
1362  (*(Psegments_noL6[ pseg_noL6_pos ].end()-2 ))->localPosition().x(),
1363  (*(Psegments_noL6[ pseg_noL6_pos ].end()-3 ))->localPosition().x(),
1364  float((*(Psegments_noL6[ pseg_noL6_pos ].end()-1))->cscDetId().layer()),
1365  float((*(Psegments_noL6[ pseg_noL6_pos ].end()-2))->cscDetId().layer()),
1366  float((*(Psegments_noL6[ pseg_noL6_pos ].end()-3))->cscDetId().layer())
1367  );
1368 
1369  weight_noL6_B[ pseg_noL6_pos ] += theWeight(
1370  (*(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 
1378  //if we have picked up the last hit go looking for pseg with the lowest (and second lowest?) weight
1379 
1380  if(int(Psegments_noL6[ pseg_noL6_pos ].size()) == n_layers_occupied_tot -1 ) {
1381 
1382  curv_noL6_A[ pseg_noL6_pos ] += theWeight(
1383  (*(Psegments_noL6[ pseg_noL6_pos ].end()-1 ))->localPosition().x(),
1384  (*(Psegments_noL6[ pseg_noL6_pos ].end()-midlayer_pointer[n_layers_occupied_tot-2] ))->localPosition().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] ))->cscDetId().layer()),
1388  float((*(Psegments_noL6[ pseg_noL6_pos ].end()-(n_layers_occupied_tot-1) ))->cscDetId().layer())
1389  );
1390 
1391  if (curv_noL6_A[ pseg_noL6_pos ] > curvePenaltyThreshold) weight_noL6_A[ pseg_noL6_pos ] = weight_noL6_A[ pseg_noL6_pos ] * curvePenalty;
1392 
1393  if (weight_noL6_B[ pseg_noL6_pos ] > a_yweightPenaltyThreshold[thestation][thering])
1394  weight_noL6_A[ pseg_noL6_pos ] = weight_noL6_A[ pseg_noL6_pos ] * yweightPenalty;
1395 
1396  if (weight_noL6_A[ pseg_noL6_pos ] < min_weight_noLx_A ) {
1397  min_weight_noLx_A = weight_noL6_A[ pseg_noL6_pos ];
1398  //best_weight_noLx_B = weight_noL6_B[ pseg_noL6_pos ];
1399  //best_curv_noLx_A = curv_noL6_A[ pseg_noL6_pos ];
1400  best_noLx_pseg = pseg_noL6_pos;
1401  best_Layer_noLx = 6;
1402  }
1403 
1404  }
1405 
1406  // alternative: fill map with weight and pseg (which is already ordered)? Seems a very good tool to go looking for segments from.
1407  // As I understand, the segments would be inserted according to their weight, so the list would "automatically" be sorted.
1408 
1409  }
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 
1433  //float chosen_weight = min_weight_A;
1434  //float chosen_ywgt = best_weight_B;
1435  //float chosen_curv = best_curv_A;
1436  //int chosen_nlayers = n_layers_occupied_tot;
1437  int chosen_pseg = best_pseg;
1438  if (best_pseg<0) {
1439  return segmentInChamber;
1440  }
1443 
1444  float hit_drop_limit = -999999.999;
1445 
1446  // define different weight improvement requirements depending on how many layers are in the segment candidate
1447  switch ( n_layers_processed ) {
1448  case 1 :
1449  // do nothing;
1450  break;
1451  case 2 :
1452  // do nothing;
1453  break;
1454  case 3 :
1455  // do nothing;
1456  break;
1457  case 4 :
1458  hit_drop_limit = hitDropLimit6Hits * (1./2.) * hitDropLimit4Hits;
1459  if ((best_Layer_noLx < 1) || (best_Layer_noLx > 4)) {
1460  // std::cout<<"CSCSegAlgoST: For four layers, best_Layer_noLx = "<< best_Layer_noLx << std::endl;
1461  }
1462  if ((best_Layer_noLx == 2) || (best_Layer_noLx == 3)) 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)) hit_drop_limit = hit_drop_limit * (1./2.);
1470  if (best_Layer_noLx == 3) hit_drop_limit = hit_drop_limit * (1./3.);
1471  break;
1472  case 6 :
1473  hit_drop_limit = hitDropLimit6Hits * (3./4.);
1474  if ((best_Layer_noLx < 1) || (best_Layer_noLx > 6)) {
1475  // std::cout<<"CSCSegAlgoST: For six layers, best_Layer_noLx = "<< best_Layer_noLx << std::endl;
1476  }
1477  if ((best_Layer_noLx == 2) || (best_Layer_noLx == 5)) hit_drop_limit = hit_drop_limit * (1./2.);
1478  if ((best_Layer_noLx == 3) || (best_Layer_noLx == 4)) hit_drop_limit = hit_drop_limit * (1./3.);
1479  break;
1480 
1481  default :
1482  // Fallback - should never occur.
1483  LogTrace("CSCSegment|CSC") << "[CSCSegAlgoST::buildSegments] Unexpected number of layers with hits - please inform CSC DPG.";
1484  hit_drop_limit = 0.1;
1485  }
1486 
1487  // choose the NoLx collection (the one that contains the best N-1 candidate)
1488  switch ( best_Layer_noLx ) {
1489  case 1 :
1490  Psegments_noLx.clear();
1492  weight_noLx_A.clear();
1494  break;
1495  case 2 :
1496  Psegments_noLx.clear();
1498  weight_noLx_A.clear();
1500  break;
1501  case 3 :
1502  Psegments_noLx.clear();
1504  weight_noLx_A.clear();
1506  break;
1507  case 4 :
1508  Psegments_noLx.clear();
1510  weight_noLx_A.clear();
1512  break;
1513  case 5 :
1514  Psegments_noLx.clear();
1516  weight_noLx_A.clear();
1518  break;
1519  case 6 :
1520  Psegments_noLx.clear();
1522  weight_noLx_A.clear();
1524  break;
1525 
1526  default :
1527  // Fallback - should occur only for preclusters with only 3 layers with hits.
1528  Psegments_noLx.clear();
1529  weight_noLx_A.clear();
1530  }
1531 
1532  if( min_weight_A > 0. ) {
1533  if ( min_weight_noLx_A/min_weight_A < hit_drop_limit ) {
1534  //chosen_weight = min_weight_noLx_A;
1535  //chosen_ywgt = best_weight_noLx_B;
1536  //chosen_curv = best_curv_noLx_A;
1537  //chosen_nlayers = n_layers_occupied_tot-1;
1538  chosen_pseg = best_noLx_pseg;
1539  chosen_Psegments.clear();
1540  chosen_weight_A.clear();
1543  }
1544  }
1545 
1546  if(onlyBestSegment) {
1547  ChooseSegments2a( chosen_Psegments, chosen_pseg );
1548  }
1549  else {
1551  }
1552 
1553  for(unsigned int iSegment=0; iSegment<GoodSegments.size();++iSegment){
1554  protoSegment = GoodSegments[iSegment];
1555  passCondNumber=false;
1556  passCondNumber_2 = false;
1557  protoChiUCorrection=1.0;
1558  doSlopesAndChi2();
1559  // Attempt to handle numerical instability of the fit;
1560  // Any segment with protoChi2/protoNDF>chi2Norm_3D_
1561  // considered as that one potentially suffering from
1562  // numerical instability in fit.
1563  if(correctCov_){
1564  // Call the fit with prefitting option;
1565  // First fit a straight line to X-Z coordinates
1566  // and calculate chi^2 (chiUZ in correctTheCovX(void)) for X-Z fit;
1567  // Scale up errors in X if chiUZ too big (default 20);
1568  // Refit XY-Z with the scaled up X errors
1570  passCondNumber = true;
1571  doSlopesAndChi2();
1572  }
1573  if(protoChiUCorrection<1.00005){
1574  LogTrace("CSCWeirdSegment") << "[CSCSegAlgoST::buildSegments] Segment ErrXX scaled and refit " << std::endl;
1576  // Call the fit with direct adjustment of condition number;
1577  // If the attempt to improve fit by scaling up X error fails
1578  // call the procedure to make the condition number of M compatible with
1579  // the precision of X and Y measurements;
1580  // Achieved by decreasing abs value of the Covariance
1581  LogTrace("CSCWeirdSegment") << "[CSCSegAlgoST::buildSegments] Segment ErrXY changed to match cond. number and refit " << std::endl;
1582  passCondNumber_2=true;
1583  doSlopesAndChi2();
1584  }
1585  }
1586  // Call the pre-pruning procedure;
1587  // If the attempt to improve fit by scaling up X error is successfull,
1588  // while scale factor for X errors is too big.
1589  // Prune the recHit inducing the biggest contribution into X-Z chi^2
1590  // and refit;
1592  (protoSegment.size()>3)){
1593  LogTrace("CSCWeirdSegment") << "[CSCSegAlgoST::buildSegments] Scale factor protoChiUCorrection too big, pre-Prune and refit " << std::endl;
1594  protoSegment.erase(protoSegment.begin()+(maxContrIndex),
1595  protoSegment.begin()+(maxContrIndex+1));
1596  doSlopesAndChi2();
1597  }
1598  }
1599 
1601  // calculate error matrix
1602  // AlgebraicSymMatrix protoErrors = calculateError();
1603  SMatrixSym4 protoErrors = calculateError();
1604  // but reorder components to match what's required by TrackingRecHit interface
1605  // i.e. slopes first, then positions
1606  AlgebraicSymMatrix temp2 = flipErrors( protoErrors ); //@@ TO SATISFY CSCSegment INTERFACE
1607 
1609 
1610  dumpSegment( temp );
1611 
1612  segmentInChamber.push_back(temp);
1613  }
1614  return segmentInChamber;
1615 }
1616 
1617 void CSCSegAlgoST::ChooseSegments2a(std::vector< ChamberHitContainer > & chosen_segments, int chosen_seg) {
1618  // just return best segment
1619  GoodSegments.clear();
1620  GoodSegments.push_back( chosen_segments[chosen_seg] );
1621 }
1622 
1623 void CSCSegAlgoST::ChooseSegments3(std::vector< ChamberHitContainer > & chosen_segments, std::vector< float > & chosen_weight, int chosen_seg) {
1624 
1625  int SumCommonHits = 0;
1626  GoodSegments.clear();
1627  int nr_remaining_candidates;
1628  unsigned int nr_of_segment_candidates;
1629 
1630  nr_remaining_candidates = nr_of_segment_candidates = chosen_segments.size();
1631 
1632  // always select and return best protosegment:
1633  GoodSegments.push_back( chosen_segments[ chosen_seg ] );
1634 
1635  float chosen_weight_temp = 999999.;
1636  int chosen_seg_temp = -1;
1637 
1638  // try to find further segment candidates:
1639  while( nr_remaining_candidates > 0 ) {
1640 
1641  for(unsigned int iCand=0; iCand < nr_of_segment_candidates; ++iCand) {
1642  //only compare current best to psegs that have not been marked bad:
1643  if( chosen_weight[iCand] < 0. ) continue;
1644  SumCommonHits = 0;
1645 
1646  for( int ihits = 0; ihits < int(chosen_segments[iCand].size()); ++ihits ) { // iCand and iiCand NEED to have same nr of hits! (always have by construction)
1647  if( chosen_segments[iCand][ihits] == chosen_segments[chosen_seg][ihits]) {
1648  ++SumCommonHits;
1649  }
1650  }
1651 
1652  //mark a pseg bad:
1653  if(SumCommonHits>1) { // needs to be a card; should be investigated first
1654  chosen_weight[iCand] = -1.;
1655  nr_remaining_candidates -= 1;
1656  }
1657  else {
1658  // save the protosegment with the smallest weight
1659  if( chosen_weight[ iCand ] < chosen_weight_temp ) {
1660  chosen_weight_temp = chosen_weight[ iCand ];
1661  chosen_seg_temp = iCand ;
1662  }
1663  }
1664  }
1665 
1666  if( chosen_seg_temp > -1 ) GoodSegments.push_back( chosen_segments[ chosen_seg_temp ] );
1667 
1668  chosen_seg = chosen_seg_temp;
1669  // re-initialze temporary best parameters
1670  chosen_weight_temp = 999999;
1671  chosen_seg_temp = -1;
1672  }
1673 }
1674 
1675 void CSCSegAlgoST::ChooseSegments2(int best_seg) {
1676  // std::vector <int> CommonHits(6); // nice concept :)
1677  std::vector <unsigned int> BadCandidate;
1678  int SumCommonHits =0;
1679  GoodSegments.clear();
1680  BadCandidate.clear();
1681  for(unsigned int iCand=0;iCand<Psegments.size();++iCand) {
1682  // skip here if segment was marked bad
1683  for(unsigned int iiCand=iCand+1;iiCand<Psegments.size();++iiCand){
1684  // skip here too if segment was marked bad
1685  SumCommonHits =0;
1686  if( Psegments[iCand].size() != Psegments[iiCand].size() ) {
1687  LogTrace("CSCSegment|CSC") << "[CSCSegAlgoST::ChooseSegments2] ALARM!! Should not happen - please inform CSC DPG";
1688  }
1689  else {
1690  for( int ihits = 0; ihits < int(Psegments[iCand].size()); ++ihits ) { // iCand and iiCand NEED to have same nr of hits! (alsways have by construction)
1691  if( Psegments[iCand][ihits] == Psegments[iiCand][ihits]) {
1692  ++SumCommonHits;
1693  }
1694  }
1695  }
1696  if(SumCommonHits>1) {
1697  if( weight_A[iCand]>weight_A[iiCand] ) { // use weight_A here
1698  BadCandidate.push_back(iCand);
1699  // 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
1700  }
1701  else{
1702  BadCandidate.push_back(iiCand);
1703  // 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
1704  }
1705  }
1706  }
1707  }
1708  bool discard;
1709  for(unsigned int isegm=0;isegm<Psegments.size();++isegm) {
1710  // For best results another iteration/comparison over Psegments
1711  //should be applied here... It would make the program much slower.
1712  discard = false;
1713  for(unsigned int ibad=0;ibad<BadCandidate.size();++ibad) {
1714  // can save this loop if we used an array in sync with Psegments!!!!
1715  if(isegm == BadCandidate[ibad]) {
1716  discard = true;
1717  }
1718  }
1719  if(!discard) {
1720  GoodSegments.push_back( Psegments[isegm] );
1721  }
1722  }
1723 }
1724 //Method doSlopesAndChi2
1725 // fitSlopes() and fillChiSquared() are always called one after the other
1726 // In fact the code is duplicated in the two functions (as we need 2 loops) -
1727 // it is much better to fix that at some point
1729  fitSlopes();
1730  fillChiSquared();
1731 }
1732 /* Method fitSlopes
1733  *
1734  * Perform a Least Square Fit on a segment as per SK algo
1735  *
1736  */
1738  e_Cxx.clear();
1740  correctTheCovX();
1741  if(e_Cxx.size()!=protoSegment.size()){
1742  LogTrace("CSCSegment|CSC") << "[CSCSegAlgoST::fitSlopes] e_Cxx.size()!=protoSegment.size() ALARM! Please inform CSC DPG " << std::endl;
1743  }
1744  }
1745 
1746  SMatrix4 M; // 4x4, init to 0
1747  SVector4 B; // 4x1, init to 0; //@@ 4x1 OR 1x4 ??
1748 
1749  ChamberHitContainer::const_iterator ih = protoSegment.begin();
1750  for (ih = protoSegment.begin(); ih != protoSegment.end(); ++ih) {
1751  const CSCRecHit2D& hit = (**ih);
1752  const CSCLayer* layer = theChamber->layer(hit.cscDetId().layer());
1753  GlobalPoint gp = layer->toGlobal(hit.localPosition());
1754  LocalPoint lp = theChamber->toLocal(gp);
1755  // Local position of hit w.r.t. chamber
1756  double u = lp.x();
1757  double v = lp.y();
1758  double z = lp.z();
1759  // Covariance matrix of local errors
1760  SMatrixSym2 IC; // 2x2, init to 0
1762  IC(0,0) = e_Cxx.at(ih-protoSegment.begin());
1763  }
1764  else{
1765  IC(0,0) = hit.localPositionError().xx();
1766  }
1767  // IC(0,1) = hit.localPositionError().xy();
1768  IC(1,0) = hit.localPositionError().xy();
1769  IC(1,1) = hit.localPositionError().yy();
1770  // IC(1,0) = IC(0,1); // since Cov is symmetric
1772  if(passCondNumber_2){
1773  correctTheCovMatrix(IC);
1774  }
1775  // Invert covariance matrix (and trap if it fails!)
1776  bool ok = IC.Invert();
1777  if ( !ok ) {
1778  LogTrace("CSCSegment|CSC") << "[CSCSegAlgoST::fitSlopes] Failed to invert covariance matrix: \n" << IC;
1779  // return ok;
1780  }
1781 
1782  M(0,0) += IC(0,0);
1783  M(0,1) += IC(0,1);
1784  M(0,2) += IC(0,0) * z;
1785  M(0,3) += IC(0,1) * z;
1786  B(0) += u * IC(0,0) + v * IC(0,1);
1787 
1788  M(1,0) += IC(1,0);
1789  M(1,1) += IC(1,1);
1790  M(1,2) += IC(1,0) * z;
1791  M(1,3) += IC(1,1) * z;
1792  B(1) += u * IC(1,0) + v * IC(1,1);
1793 
1794  M(2,0) += IC(0,0) * z;
1795  M(2,1) += IC(0,1) * z;
1796  M(2,2) += IC(0,0) * z * z;
1797  M(2,3) += IC(0,1) * z * z;
1798  B(2) += ( u * IC(0,0) + v * IC(0,1) ) * z;
1799 
1800  M(3,0) += IC(1,0) * z;
1801  M(3,1) += IC(1,1) * z;
1802  M(3,2) += IC(1,0) * z * z;
1803  M(3,3) += IC(1,1) * z * z;
1804  B(3) += ( u * IC(1,0) + v * IC(1,1) ) * z;
1805 
1806  }
1807 
1808  SVector4 p;
1809  bool ok = M.Invert();
1810  if (!ok ){
1811  LogTrace("CSCSegment|CSC") << "[CSCSegAlgoST::fitSlopes[ Failed to invert matrix: \n" << M;
1812  // return ok;
1813  }
1814  else {
1815  p = M * B;
1816  }
1817 
1818  // Update member variables
1819  // Note that origin has local z = 0
1820 
1821  protoIntercept = LocalPoint(p(0), p(1), 0.);
1822  protoSlope_u = p(2);
1823  protoSlope_v = p(3);
1824 
1825  // LogTrace("CSCSegAlgoST") << "[CSCSegAlgoST::fillSlopes] p = "
1826  // << p(0) << ", " << p(1) << ", " << p(2) << ", " << p(3);
1827 
1828 }
1829 /* Method fillChiSquared
1830  *
1831  * Determine Chi^2 for the proto wire segment
1832  *
1833  */
1835 
1836  double chsq = 0.;
1837 
1838  ChamberHitContainer::const_iterator ih;
1839  for (ih = protoSegment.begin(); ih != protoSegment.end(); ++ih) {
1840 
1841  const CSCRecHit2D& hit = (**ih);
1842  const CSCLayer* layer = theChamber->layer(hit.cscDetId().layer());
1843  GlobalPoint gp = layer->toGlobal(hit.localPosition());
1844  LocalPoint lp = theChamber->toLocal(gp);
1845 
1846  double u = lp.x();
1847  double v = lp.y();
1848  double z = lp.z();
1849 
1850  double du = protoIntercept.x() + protoSlope_u * z - u;
1851  double dv = protoIntercept.y() + protoSlope_v * z - v;
1852 
1853  // LogTrace("CSCSegAlgoST") << "[CSCSegAlgoST::fillChiSquared] u, v, z = " << u << ", " << v << ", " << z;
1854 
1855  SMatrixSym2 IC; // 2x2, init to 0
1856 
1858  IC(0,0) = e_Cxx.at(ih-protoSegment.begin());
1859  }
1860  else{
1861  IC(0,0) = hit.localPositionError().xx();
1862  }
1863  // IC(0,1) = hit.localPositionError().xy();
1864  IC(1,0) = hit.localPositionError().xy();
1865  IC(1,1) = hit.localPositionError().yy();
1866  // IC(1,0) = IC(0,1);
1867 
1868  // LogTrace("CSCSegAlgoST") << "[CSCSegAlgoST::fillChiSquared] IC before = \n" << IC;
1869 
1871  if(passCondNumber_2){
1872  correctTheCovMatrix(IC);
1873  }
1874 
1875  // Invert covariance matrix
1876  bool ok = IC.Invert();
1877  if (!ok ){
1878  LogTrace("CSCSegment|CSC") << "[CSCSegAlgoST::fillChiSquared] Failed to invert covariance matrix: \n" << IC;
1879  // return ok;
1880  }
1881  // LogTrace("CSCSegAlgoST") << "[CSCSegAlgoST::fillChiSquared] IC after = \n" << IC;
1882  chsq += du*du*IC(0,0) + 2.*du*dv*IC(0,1) + dv*dv*IC(1,1);
1883  }
1884  protoChi2 = chsq;
1885  protoNDF = 2.*protoSegment.size() - 4;
1886 
1887  // LogTrace("CSCSegAlgoST") << "[CSCSegAlgoST::fillChiSquared] chi2 = " << protoChi2 << "/" << protoNDF << " dof";
1888 
1889 }
1890 
1891 /* fillLocalDirection
1892  *
1893  */
1895  // Always enforce direction of segment to point from IP outwards
1896  // (Incorrect for particles not coming from IP, of course.)
1897 
1898  double dxdz = protoSlope_u;
1899  double dydz = protoSlope_v;
1900  double dz = 1./sqrt(1. + dxdz*dxdz + dydz*dydz);
1901  double dx = dz*dxdz;
1902  double dy = dz*dydz;
1903  LocalVector localDir(dx,dy,dz);
1904 
1905  // localDir may need sign flip to ensure it points outward from IP
1906  // Examine its direction and origin in global z: to point outward
1907  // the localDir should always have same sign as global z...
1908 
1909  double globalZpos = ( theChamber->toGlobal( protoIntercept ) ).z();
1910  double globalZdir = ( theChamber->toGlobal( localDir ) ).z();
1911  double directionSign = globalZpos * globalZdir;
1912  protoDirection = (directionSign * localDir).unit();
1913 }
1914 
1915 /* weightMatrix
1916  *
1917  */
1918 // AlgebraicSymMatrix CSCSegAlgoST::weightMatrix() const {
1920 
1921  std::vector<const CSCRecHit2D*>::const_iterator it;
1922 
1923  bool ok = true;
1924 
1925  SMatrixSym12 matrix = ROOT::Math::SMatrixIdentity(); // 12x12, init to 1's on diag
1926 
1927  int row = 0;
1928 
1929  for (it = protoSegment.begin(); it != protoSegment.end(); ++it) {
1930 
1931  const CSCRecHit2D& hit = (**it);
1932 
1933  matrix(row, row) = protoChiUCorrection*hit.localPositionError().xx();
1934  matrix(row, row+1) = hit.localPositionError().xy();
1935  ++row;
1936  matrix(row, row-1) = hit.localPositionError().xy();
1937  matrix(row, row) = hit.localPositionError().yy();
1938  ++row;
1939  }
1940 
1941  ok = matrix.Invert(); // invert in place
1942  if ( !ok ) {
1943  LogTrace("CSCSegment|CSC") << "[CSCSegAlgoST::weightMatrix] Failed to invert matrix: \n" << matrix;
1944  // return ok;
1945  }
1946  return matrix;
1947 }
1948 
1949 
1950 /* derivativeMatrix
1951  *
1952  */
1953 // CLHEP::HepMatrix CSCSegAlgoST::derivativeMatrix() const {
1955 
1956  ChamberHitContainer::const_iterator it;
1957 
1958  SMatrix12by4 matrix; // 12x4, init to 0
1959  int row = 0;
1960 
1961  for(it = protoSegment.begin(); it != protoSegment.end(); ++it) {
1962 
1963  const CSCRecHit2D& hit = (**it);
1964  const CSCLayer* layer = theChamber->layer(hit.cscDetId().layer());
1965  GlobalPoint gp = layer->toGlobal(hit.localPosition());
1966  LocalPoint lp = theChamber->toLocal(gp);
1967  float z = lp.z();
1968 
1969  matrix(row, 0) = 1.;
1970  matrix(row, 2) = z;
1971  ++row;
1972  matrix(row, 1) = 1.;
1973  matrix(row, 3) = z;
1974  ++row;
1975  }
1976  return matrix;
1977 }
1978 
1979 
1980 /* calculateError
1981  *
1982  */
1983 
1985 
1988  // LogTrace("CSCSegAlgoST") << "[CSCSegAlgoST::calculateError] weights matrix W: \n" << weights;
1989  // LogTrace("CSCSegAlgoST") << "[CSCSegAlgoST::calculateError] derivatives matrix A: \n" << A;
1990 
1991  // (AT W A)^-1
1992  // from http://www.phys.ufl.edu/~avery/fitting.html, part I
1993 
1994  bool ok;
1995  SMatrixSym4 result = ROOT::Math::SimilarityT(A, weights);
1996  // LogTrace("CSCSegAlgoST") << "[CSCSegAlgoST::calculateError] (AT W A): \n" << result;
1997  ok = result.Invert(); // inverts in place
1998  if ( !ok ) {
1999  LogTrace("CSCSegment|CSC") << "[CSCSegAlgoST::calculateError] Failed to invert matrix: \n" << result;
2000  // return ok;
2001  }
2002  // LogTrace("CSCSegAlgoST") << "[CSCSegAlgoST::calculateError] (AT W A)^-1: \n" << result;
2003  // blithely assuming the inverting never fails...
2004  return result;
2005 }
2006 
2007 
2009 
2010  // The CSCSegment needs the error matrix re-arranged to match
2011  // parameters in order (uz, vz, u0, v0) where uz, vz = slopes, u0, v0 = intercepts
2012 
2013  // LogTrace("CSCSegAlgoST") << "[CSCSegAlgoST::flipErrors] input: \n" << a;
2014 
2015  AlgebraicSymMatrix hold(4, 0. );
2016 
2017  for ( short j=0; j!=4; ++j) {
2018  for (short i=0; i!=4; ++i) {
2019  hold(i+1,j+1) = a(i,j); // SMatrix counts from 0, AlgebraicMatrix from 1
2020  }
2021  }
2022 
2023  // LogTrace("CSCSegAlgoST") << "[CSCSegAlgoST::flipErrors] after copy:";
2024  // LogTrace("CSCSegAlgoST") << "(" << hold(1,1) << " " << hold(1,2) << " " << hold(1,3) << " " << hold(1,4);
2025  // LogTrace("CSCSegAlgoST") << " " << hold(2,1) << " " << hold(2,2) << " " << hold(2,3) << " " << hold(2,4);
2026  // LogTrace("CSCSegAlgoST") << " " << hold(3,1) << " " << hold(3,2) << " " << hold(3,3) << " " << hold(3,4);
2027  // LogTrace("CSCSegAlgoST") << " " << hold(4,1) << " " << hold(4,2) << " " << hold(4,3) << " " << hold(4,4) << ")";
2028 
2029  // errors on slopes into upper left
2030  hold(1,1) = a(2,2);
2031  hold(1,2) = a(2,3);
2032  hold(2,1) = a(3,2);
2033  hold(2,2) = a(3,3);
2034 
2035  // errors on positions into lower right
2036  hold(3,3) = a(0,0);
2037  hold(3,4) = a(0,1);
2038  hold(4,3) = a(1,0);
2039  hold(4,4) = a(1,1);
2040 
2041  // must also interchange off-diagonal elements of off-diagonal 2x2 submatrices
2042  hold(4,1) = a(1,2);
2043  hold(3,2) = a(0,3);
2044  hold(2,3) = a(3,0); // = a(0,3)
2045  hold(1,4) = a(2,1); // = a(1,2)
2046 
2047  // LogTrace("CSCSegAlgoST") << "[CSCSegAlgoST::flipErrors] after flip:";
2048  // LogTrace("CSCSegAlgoST") << "(" << hold(1,1) << " " << hold(1,2) << " " << hold(1,3) << " " << hold(1,4);
2049  // LogTrace("CSCSegAlgoST") << " " << hold(2,1) << " " << hold(2,2) << " " << hold(2,3) << " " << hold(2,4);
2050  // LogTrace("CSCSegAlgoST") << " " << hold(3,1) << " " << hold(3,2) << " " << hold(3,3) << " " << hold(3,4);
2051  // LogTrace("CSCSegAlgoST") << " " << hold(4,1) << " " << hold(4,2) << " " << hold(4,3) << " " << hold(4,4) << ")";
2052 
2053  return hold;
2054 }
2055 
2057  std::vector<double> uu, vv, zz;
2058  //std::vector<double> e_Cxx;
2059  e_Cxx.clear();
2060  double sum_U_err=0.0;
2061  double sum_Z_U_err=0.0;
2062  double sum_Z2_U_err=0.0;
2063  double sum_U_U_err=0.0;
2064  double sum_UZ_U_err=0.0;
2065  std::vector<double> chiUZind;
2066  std::vector<double>::iterator chiContribution;
2067  double chiUZ=0.0;
2068  ChamberHitContainer::const_iterator ih = protoSegment.begin();
2069  for (ih = protoSegment.begin(); ih != protoSegment.end(); ++ih) {
2070  const CSCRecHit2D& hit = (**ih);
2071  e_Cxx.push_back(hit.localPositionError().xx());
2072 
2073  const CSCLayer* layer = theChamber->layer(hit.cscDetId().layer());
2074  GlobalPoint gp = layer->toGlobal(hit.localPosition());
2075  LocalPoint lp = theChamber->toLocal(gp);
2076  // Local position of hit w.r.t. chamber
2077  double u = lp.x();
2078  double v = lp.y();
2079  double z = lp.z();
2080  uu.push_back(u);
2081  vv.push_back(v);
2082  zz.push_back(z);
2083  // Prepare the sums for the standard linear fit
2084  sum_U_err += 1./e_Cxx.back();
2085  sum_Z_U_err += z/e_Cxx.back();
2086  sum_Z2_U_err += (z*z)/e_Cxx.back();
2087  sum_U_U_err += u/e_Cxx.back();
2088  sum_UZ_U_err += (u*z)/e_Cxx.back();
2089  }
2090 
2093 
2094  double denom=sum_U_err*sum_Z2_U_err-pow(sum_Z_U_err,2);
2095  double U0=(sum_Z2_U_err*sum_U_U_err-sum_Z_U_err*sum_UZ_U_err)/denom;
2096  double UZ=(sum_U_err*sum_UZ_U_err-sum_Z_U_err*sum_U_U_err)/denom;
2097 
2100 
2101  for(unsigned i=0; i<uu.size(); ++i){
2102  double uMean = U0+UZ*zz[i];
2103  chiUZind.push_back((pow((uMean-uu[i]),2))/e_Cxx[i]);
2104  chiUZ += (pow((uMean-uu[i]),2))/e_Cxx[i];
2105  }
2106  chiUZ = chiUZ/(uu.size()-2);
2107 
2108  if(chiUZ>=chi2Norm_2D_){
2110  for(unsigned i=0; i<uu.size(); ++i)
2112  }
2113 
2115 
2117  chiContribution=max_element(chiUZind.begin(),chiUZind.end());
2118  maxContrIndex = chiContribution - chiUZind.begin();
2119  /*
2120  for(unsigned i=0; i<chiUZind.size();++i){
2121  if(*chiContribution==chiUZind[i]){
2122  maxContrIndex=i;
2123  }
2124  }
2125  */
2126  }
2127  //
2128  //return e_Cxx;
2129 }
2130 
2132  //double condNumberCorr1=0.0;
2133  double condNumberCorr2=0.0;
2134  double detCov=0.0;
2135  double diag1=0.0;
2136  double diag2=0.0;
2137  double IC_01_corr=0.0;
2138  double IC_00_corr=0.0;
2139  if(!covToAnyNumberAll_){
2140  //condNumberCorr1=condSeed1_*IC(1,1);
2141  condNumberCorr2=condSeed2_*IC(1,1);
2142  diag1=IC(0,0)*IC(1,1);
2143  diag2=IC(0,1)*IC(0,1);
2144  detCov=fabs(diag1-diag2);
2145  if((diag1<condNumberCorr2)&&(diag2<condNumberCorr2)){
2146  if(covToAnyNumber_)
2147  IC(0,1)=covAnyNumber_;
2148  else{
2149  IC_00_corr=condSeed1_+fabs(IC(0,1))/IC(1,1);
2150  IC(0,0)=IC_00_corr;
2151  }
2152  }
2153 
2154  if(((detCov<condNumberCorr2)&&(diag1>condNumberCorr2))||
2155  ((diag2>condNumberCorr2)&&(detCov<condNumberCorr2)
2156  )){
2157  if(covToAnyNumber_)
2158  IC(0,1)=covAnyNumber_;
2159  else{
2160  IC_01_corr=sqrt(fabs(diag1-condNumberCorr2));
2161  if(IC(0,1)<0)
2162  IC(0,1)=(-1)*IC_01_corr;
2163  else
2164  IC(0,1)=IC_01_corr;
2165  }
2166  }
2167  }
2168  else{
2169  IC(0,1)=covAnyNumber_;
2170  }
2171  IC(1,0) = IC(0,1); //@@ ADDED TO MAINTAIN SYMMETRIC
2172 }
2173 //
2174 void CSCSegAlgoST::findDuplicates(std::vector<CSCSegment> & segments ){
2175  // this is intended for ME1/1a only - we have ghost segments because of the strips ganging
2176  // this function finds them (first the rechits by sharesInput() )
2177  // if a segment shares all the rechits with another segment it is a duplicate (even if
2178  // it has less rechits)
2179 
2180  for(std::vector<CSCSegment>::iterator it=segments.begin(); it != segments.end(); ++it) {
2181  std::vector<CSCSegment*> duplicateSegments;
2182  for(std::vector<CSCSegment>::iterator it2=segments.begin(); it2 != segments.end(); ++it2) {
2183  //
2184  bool allShared = true;
2185  if(it!=it2){
2186  allShared = it->sharesRecHits(*it2);
2187  }
2188  else{
2189  allShared = false;
2190  }
2191  //
2192  if(allShared){
2193  duplicateSegments.push_back(&(*it2));
2194  }
2195  }
2196  it->setDuplicateSegments(duplicateSegments);
2197  }
2198 
2199 }
2200 
2201 void CSCSegAlgoST::dumpSegment( const CSCSegment& seg ) const {
2202  LogTrace("CSCSegment") << "CSCSegment in " << chamber()->id()
2203  << "\nlocal position = " << seg.localPosition()
2204  << "\nerror = " << seg.localPositionError()
2205  << "\nlocal direction = " << seg.localDirection()
2206  << "\nerror =" << seg.localDirectionError()
2207  << "\ncovariance matrix"
2208  << seg.parametersError()
2209  << "chi2/ndf = " << seg.chi2() << "/" << seg.degreesOfFreedom()
2210  << "\n#rechits = " << seg.specificRecHits().size();
2211 }
2212 
2213 
double yweightPenaltyThreshold
Definition: CSCSegAlgoST.h:219
T getParameter(std::string const &) const
double protoChiUCorrection
Allow to correct the error matrix.
Definition: CSCSegAlgoST.h:228
T getUntrackedParameter(std::string const &, T const &) const
int i
Definition: DBlmapReader.cc:9
float xx() const
Definition: LocalError.h:24
bool preClustering_useChaining
Definition: CSCSegAlgoST.h:206
CSCDetId cscDetId() const
Definition: CSCRecHit2D.h:52
bool passCondNumber
The number to force the Covariance.
Definition: CSCSegAlgoST.h:242
void doSlopesAndChi2(void)
std::vector< ChamberHitContainer > Psegments_noL5
Definition: CSCSegAlgoST.h:158
std::vector< float > curv_noL2_A
Definition: CSCSegAlgoST.h:172
double dXclusBoxMax
Definition: CSCSegAlgoST.h:202
const CSCChamber * chamber() const
Definition: CSCSegAlgoST.h:142
CSCDetId id() const
Get the (concrete) DetId.
Definition: CSCChamber.h:37
void dumpSegment(const CSCSegment &seg) const
double_binary B
Definition: DDStreamer.cc:234
CSCSegment showerSeg(const CSCChamber *aChamber, const ChamberHitContainer &rechits)
const CSCChamber * theChamber
Definition: CSCSegAlgoST.h:146
std::vector< float > weight_noL4_A
Definition: CSCSegAlgoST.h:166
void correctTheCovX(void)
std::vector< float > curv_noL6_A
Definition: CSCSegAlgoST.h:176
GlobalPoint toGlobal(const Local2DPoint &lp) const
Conversion to the global R.F. from the R.F. of the GeomDet.
Definition: GeomDet.h:52
std::vector< CSCSegment > run(const CSCChamber *aChamber, const ChamberHitContainer &rechits)
Definition: CSCSegAlgoST.cc:95
void ChooseSegments2(int best_seg)
void ChooseSegments3(int best_seg)
LocalError localPositionError() const
Definition: CSCSegment.cc:47
std::vector< float > weight_noL3_B
Definition: CSCSegAlgoST.h:180
T y() const
Definition: PV3DBase.h:63
float protoSlope_v
Definition: CSCSegAlgoST.h:189
LocalPoint toLocal(const GlobalPoint &gp) const
Conversion to the R.F. of the GeomDet.
Definition: GeomDet.h:67
std::vector< ChamberHitContainer > Psegments_noL1
Definition: CSCSegAlgoST.h:154
CSCSegAlgoST(const edm::ParameterSet &ps)
Constructor.
Definition: CSCSegAlgoST.cc:31
bool isGoodToMerge(bool isME11a, ChamberHitContainer &newChain, ChamberHitContainer &oldChain)
void correctTheCovMatrix(SMatrixSym2 &IC)
std::vector< ChamberHitContainer > chosen_Psegments
Definition: CSCSegAlgoST.h:160
std::vector< ChamberHitContainer > Psegments
Definition: CSCSegAlgoST.h:152
ChamberHitContainer protoSegment
Definition: CSCSegAlgoST.h:187
int layer() const
Definition: CSCDetId.h:74
ROOT::Math::SVector< double, 4 > SVector4
Definition: CSCSegAlgoST.h:63
float protoSlope_u
Definition: CSCSegAlgoST.h:188
float float float z
std::vector< std::vector< const CSCRecHit2D * > > clusterHits(const CSCChamber *aChamber, const ChamberHitContainer &rechits)
double condSeed1_
The upper limit of protoChiUCorrection to apply prePrun.
Definition: CSCSegAlgoST.h:238
LocalVector protoDirection
Definition: CSCSegAlgoST.h:193
std::vector< float > weight_noL3_A
Definition: CSCSegAlgoST.h:165
double hitDropLimit4Hits
Definition: CSCSegAlgoST.h:213
virtual int degreesOfFreedom() const
Degrees of freedom of the segment fit.
Definition: CSCSegment.h:61
std::string chamberTypeName() const
LocalPoint localPosition() const
Definition: CSCSegment.h:38
LocalVector localDirection() const
Local direction.
Definition: CSCSegment.h:41
float xy() const
Definition: LocalError.h:25
CSCSegAlgoShowering * showering_
Definition: CSCSegAlgoST.h:224
int nRecHits() const
Definition: CSCSegment.h:67
virtual ~CSCSegAlgoST()
Destructor.
Definition: CSCSegAlgoST.cc:90
const CSCChamberSpecs * specs() const
Definition: CSCChamber.h:42
LocalError localPositionError() const
Definition: CSCRecHit2D.h:51
double BPMinImprovement
Definition: CSCSegAlgoST.h:209
float yy() const
Definition: LocalError.h:26
double covAnyNumber_
Allow to use any number for covariance for all RecHits.
Definition: CSCSegAlgoST.h:241
string unit
Definition: csvLumiCalc.py:46
T sqrt(T t)
Definition: SSEVec.h:48
std::vector< ChamberHitContainer > Psegments_noLx
Definition: CSCSegAlgoST.h:153
double curvePenaltyThreshold
Definition: CSCSegAlgoST.h:222
std::vector< std::vector< const CSCRecHit2D * > > chainHits(const CSCChamber *aChamber, const ChamberHitContainer &rechits)
T z() const
Definition: PV3DBase.h:64
std::vector< ChamberHitContainer > Psegments_noL4
Definition: CSCSegAlgoST.h:157
tuple result
Definition: query.py:137
double protoNDF
Definition: CSCSegAlgoST.h:192
double hitDropLimit6Hits
Definition: CSCSegAlgoST.h:215
double protoChi2
Definition: CSCSegAlgoST.h:191
std::vector< float > weight_A
Definition: CSCSegAlgoST.h:161
std::vector< float > weight_noL1_B
Definition: CSCSegAlgoST.h:178
int j
Definition: DBlmapReader.cc:9
const CSCLayer * layer(CSCDetId id) const
Return the layer corresponding to the given id.
Definition: CSCChamber.cc:39
double chi2Norm_2D_
Definition: CSCSegAlgoST.h:230
std::vector< CSCSegment > buildSegments(const ChamberHitContainer &rechits)
float ChiSquaredProbability(double chiSquared, double nrDOF)
std::vector< CSCSegment > prune_bad_hits(const CSCChamber *aChamber, std::vector< CSCSegment > &segments)
void fitSlopes(void)
std::vector< float > curv_noL5_A
Definition: CSCSegAlgoST.h:175
std::vector< ChamberHitContainer > Psegments_noL6
Definition: CSCSegAlgoST.h:159
SMatrix12by4 derivativeMatrix(void) const
#define end
Definition: vmac.h:37
bool gangedStrips() const
unsigned maxContrIndex
Chi^2 normalization for the initial fit.
Definition: CSCSegAlgoST.h:232
std::vector< const CSCRecHit2D * > ChamberHitContainer
Typedefs.
Definition: CSCSegAlgoST.h:45
bool onlyBestSegment
Definition: CSCSegAlgoST.h:210
const std::vector< CSCRecHit2D > & specificRecHits() const
Definition: CSCSegment.h:65
#define LogTrace(id)
std::vector< ChamberHitContainer > Psegments_noL2
Definition: CSCSegAlgoST.h:155
ROOT::Math::SMatrix< double, 4 > SMatrix4
Definition: CSCSegAlgoST.h:56
std::vector< float > weight_noL5_A
Definition: CSCSegAlgoST.h:167
bool passCondNumber_2
Passage the condition number calculations.
Definition: CSCSegAlgoST.h:243
ROOT::Math::SMatrix< double, 12, 12, ROOT::Math::MatRepSym< double, 12 > > SMatrixSym12
Definition: CSCSegAlgoST.h:50
std::vector< float > weight_noL1_A
Definition: CSCSegAlgoST.h:163
std::vector< float > curv_noL4_A
Definition: CSCSegAlgoST.h:174
std::vector< float > weight_noL2_A
Definition: CSCSegAlgoST.h:164
std::vector< float > chosen_weight_A
Definition: CSCSegAlgoST.h:169
Segments GoodSegments
Definition: CSCSegAlgoST.h:147
AlgebraicSymMatrix parametersError() const
Covariance matrix of parameters()
Definition: CSCSegment.h:48
bool correctCov_
Correct the Error Matrix.
Definition: CSCSegAlgoST.h:227
int minHitsPerSegment
Definition: CSCSegAlgoST.h:199
ChamberHitContainer Psegments_hits
Definition: CSCSegAlgoST.h:150
double dYclusBoxMax
Definition: CSCSegAlgoST.h:203
void findDuplicates(std::vector< CSCSegment > &segments)
std::vector< float > curv_noL1_A
Definition: CSCSegAlgoST.h:171
void fillChiSquared(void)
SMatrixSym4 calculateError(void) const
bool covToAnyNumberAll_
Allow to use any number for covariance (by hand)
Definition: CSCSegAlgoST.h:240
double b
Definition: hdecay.h:120
double theWeight(double coordinate_1, double coordinate_2, double coordinate_3, float layer_1, float layer_2, float layer_3)
Utility functions.
double curvePenalty
Definition: CSCSegAlgoST.h:223
std::vector< float > curv_A
Definition: CSCSegAlgoST.h:170
ROOT::Math::SMatrix< double, 4, 4, ROOT::Math::MatRepSym< double, 4 > > SMatrixSym4
Definition: CSCSegAlgoST.h:57
#define begin
Definition: vmac.h:30
bool prePrun_
The index of the worst x RecHit in Chi^2-X method.
Definition: CSCSegAlgoST.h:233
double chi2() const
Chi2 of the segment fit.
Definition: CSCSegment.h:57
ROOT::Math::SMatrix< double, 12, 4 > SMatrix12by4
Definition: CSCSegAlgoST.h:53
double a
Definition: hdecay.h:121
bool preClustering
Definition: CSCSegAlgoST.h:205
double yweightPenalty
Definition: CSCSegAlgoST.h:220
CLHEP::HepSymMatrix AlgebraicSymMatrix
std::vector< float > weight_noL5_B
Definition: CSCSegAlgoST.h:182
std::vector< float > weight_B
Definition: CSCSegAlgoST.h:177
float a_yweightPenaltyThreshold[5][5]
Definition: CSCSegAlgoST.h:217
void ChooseSegments2a(std::vector< ChamberHitContainer > &best_segments, int best_seg)
Local3DPoint LocalPoint
Definition: LocalPoint.h:11
std::vector< double > e_Cxx
Definition: CSCSegAlgoST.h:229
void fillLocalDirection(void)
int maxRecHitsInCluster
Definition: CSCSegAlgoST.h:204
ROOT::Math::SMatrix< double, 2, 2, ROOT::Math::MatRepSym< double, 2 > > SMatrixSym2
Definition: CSCSegAlgoST.h:60
Definition: DDAxes.h:10
std::vector< float > weight_noL6_A
Definition: CSCSegAlgoST.h:168
LocalPoint localPosition() const
Definition: CSCRecHit2D.h:50
std::vector< float > weight_noL2_B
Definition: CSCSegAlgoST.h:179
bool covToAnyNumber_
The correction parameters.
Definition: CSCSegAlgoST.h:239
double hitDropLimit5Hits
Definition: CSCSegAlgoST.h:214
std::vector< float > weight_noLx_A
Definition: CSCSegAlgoST.h:162
std::vector< float > curv_noL3_A
Definition: CSCSegAlgoST.h:173
SMatrixSym12 weightMatrix(void) const
std::vector< float > weight_noL6_B
Definition: CSCSegAlgoST.h:183
T x() const
Definition: PV3DBase.h:62
tuple size
Write out results.
AlgebraicSymMatrix flipErrors(const SMatrixSym4 &) const
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:40
ChamberHitContainer PAhits_onLayer[6]
Definition: CSCSegAlgoST.h:149
LocalError localDirectionError() const
Error on the local direction.
Definition: CSCSegment.cc:51
LocalPoint protoIntercept
Definition: CSCSegAlgoST.h:190
double condSeed2_
Definition: CSCSegAlgoST.h:238
std::vector< float > weight_noL4_B
Definition: CSCSegAlgoST.h:181
std::vector< ChamberHitContainer > Psegments_noL3
Definition: CSCSegAlgoST.h:156
double chi2Norm_3D_
Chi^2 normalization for the corrected fit.
Definition: CSCSegAlgoST.h:231
double prePrunLimit_
Definition: CSCSegAlgoST.h:235