CMS 3D CMS Logo

SETSeedFinder.cc
Go to the documentation of this file.
1 
15 
16 #include "TMath.h"
17 
18 using namespace edm;
19 using namespace std;
20 
21 const string metname = "Muon|RecoMuon|SETMuonSeedFinder";
22 
24  // Parameter set for the Builder
25  ParameterSet trajectoryBuilderParameters = parameterSet.getParameter<ParameterSet>("SETTrajBuilderParameters");
26  apply_prePruning = trajectoryBuilderParameters.getParameter<bool>("Apply_prePruning");
27  // load pT seed parameters
28  thePtExtractor = new MuonSeedPtExtractor(trajectoryBuilderParameters);
29 }
30 
31 void SETSeedFinder::seeds(const MuonRecHitContainer& cluster, std::vector<TrajectorySeed>& result) {}
32 
33 // there is an existing sorter somewhere in the CMSSW code (I think) - delete that
34 namespace {
35  struct sorter {
36  sorter() {}
39  return (hit_1->globalPosition().mag2() < hit_2->globalPosition().mag2());
40  }
41  }; // smaller first
42  const sorter sortSegRadius;
43 } // namespace
44 
45 std::vector<SETSeedFinder::MuonRecHitContainer> SETSeedFinder::sortByLayer(MuonRecHitContainer& cluster) const {
46  stable_sort(cluster.begin(), cluster.end(), sortSegRadius);
47  //---- group hits in detector layers (if in same layer); the idea is that
48  //---- some hits could not belong to a track simultaneously - these will be in a
49  //---- group; two hits from one and the same group will not go to the same track
50  std::vector<MuonRecHitContainer> MuonRecHitContainer_perLayer;
51  if (!cluster.empty()) {
52  int iHit = 0;
53  MuonRecHitContainer hitsInThisLayer;
54  hitsInThisLayer.push_back(cluster[iHit]);
55  DetId detId = cluster[iHit]->hit()->geographicalId();
56  const GeomDet* geomDet = theService->trackingGeometry()->idToDet(detId);
57  while (iHit < int(cluster.size()) - 1) {
58  DetId detId_2 = cluster[iHit + 1]->hit()->geographicalId();
59  const GlobalPoint gp_nextHit = cluster[iHit + 1]->globalPosition();
60 
61  // this is the distance of the "second" hit to the "first" detector (containing the "first hit")
62  float distanceToDetector = fabs(geomDet->surface().localZ(gp_nextHit));
63 
64  //---- hits from DT and CSC could be very close in angle but incosistent with
65  //---- belonging to a common track (and these are different surfaces);
66  //---- also DT (and CSC now - 090822) hits from a station (in a pre-cluster) should be always in a group together;
67  //---- take this into account and put such hits in a group together
68 
69  bool specialCase = false;
70  if (detId.subdetId() == MuonSubdetId::DT && detId_2.subdetId() == MuonSubdetId::DT) {
71  DTChamberId dtCh(detId);
72  DTChamberId dtCh_2(detId_2);
73  specialCase = (dtCh.station() == dtCh_2.station());
74  } else if (detId.subdetId() == MuonSubdetId::CSC && detId_2.subdetId() == MuonSubdetId::CSC) {
75  CSCDetId cscCh(detId);
76  CSCDetId cscCh_2(detId_2);
77  specialCase = (cscCh.station() == cscCh_2.station() && cscCh.ring() == cscCh_2.ring());
78  }
79 
80  if (distanceToDetector < 0.001 || true == specialCase) { // hardcoded value - remove!
81  hitsInThisLayer.push_back(cluster[iHit + 1]);
82  } else {
83  specialCase = false;
84  if (((cluster[iHit]->isDT() && cluster[iHit + 1]->isCSC()) ||
85  (cluster[iHit]->isCSC() && cluster[iHit + 1]->isDT())) &&
86  //---- what is the minimal distance between a DT and a CSC hit belonging
87  //---- to a common track? (well, with "reasonable" errors; put 10 cm for now)
88  fabs(cluster[iHit + 1]->globalPosition().mag() - cluster[iHit]->globalPosition().mag()) < 10.) {
89  hitsInThisLayer.push_back(cluster[iHit + 1]);
90  // change to Stoyan - now we also update the detID here... give it a try. IBL 080905
91  detId = cluster[iHit + 1]->hit()->geographicalId();
92  geomDet = theService->trackingGeometry()->idToDet(detId);
93  } else if (!specialCase) {
94  //---- put the group of hits in the vector (containing the groups of hits)
95  //---- and continue with next layer (group)
96  MuonRecHitContainer_perLayer.push_back(hitsInThisLayer);
97  hitsInThisLayer.clear();
98  hitsInThisLayer.push_back(cluster[iHit + 1]);
99  detId = cluster[iHit + 1]->hit()->geographicalId();
100  geomDet = theService->trackingGeometry()->idToDet(detId);
101  }
102  }
103  ++iHit;
104  }
105  MuonRecHitContainer_perLayer.push_back(hitsInThisLayer);
106  }
107  return MuonRecHitContainer_perLayer;
108 }
109 //
110 void SETSeedFinder::limitCombinatorics(std::vector<MuonRecHitContainer>& MuonRecHitContainer_perLayer) {
111  const int maximumNumberOfCombinations = 1000000;
112  unsigned nLayers = MuonRecHitContainer_perLayer.size();
113  if (1 == nLayers) {
114  return;
115  }
116  // maximal number of (segment) layers would be upto ~12; see next function
117  // below is just a quick fix for a rare "overflow"
118  if (MuonRecHitContainer_perLayer.size() > 15) {
119  MuonRecHitContainer_perLayer.resize(1);
120  return;
121  }
122 
123  std::vector<double> sizeOfLayer(nLayers);
124  //std::cout<<" nLayers = "<<nLayers<<std::endl;
125  double nAllCombinations = 1.;
126  for (unsigned int i = 0; i < nLayers; ++i) {
127  //std::cout<<" i = "<<i<<" size = "<<MuonRecHitContainer_perLayer.at(i).size()<<std::endl;
128  sizeOfLayer.at(i) = MuonRecHitContainer_perLayer.at(i).size();
129  nAllCombinations *= MuonRecHitContainer_perLayer.at(i).size();
130  }
131  //std::cout<<"nAllCombinations = "<<nAllCombinations<<std::endl;
132  //---- Erase most busy detector layers until we get less than maximumNumberOfCombinations combinations
133  while (nAllCombinations > float(maximumNumberOfCombinations)) {
134  std::vector<double>::iterator maxEl_it = max_element(sizeOfLayer.begin(), sizeOfLayer.end());
135  int maxEl = maxEl_it - sizeOfLayer.begin();
136  nAllCombinations /= MuonRecHitContainer_perLayer.at(maxEl).size();
137  MuonRecHitContainer_perLayer.erase(MuonRecHitContainer_perLayer.begin() + maxEl);
138  sizeOfLayer.erase(sizeOfLayer.begin() + maxEl);
139  }
140  return;
141 }
142 //
143 std::vector<SETSeedFinder::MuonRecHitContainer> SETSeedFinder::findAllValidSets(
144  const std::vector<SETSeedFinder::MuonRecHitContainer>& MuonRecHitContainer_perLayer) {
145  std::vector<MuonRecHitContainer> allValidSets;
146  // build all possible combinations (i.e valid sets; the algorithm name is after this feature -
147  // SET algorithm)
148  //
149  // ugly... use recursive function?!
150  // or implement Ingo's suggestion (a la ST)
151  unsigned nLayers = MuonRecHitContainer_perLayer.size();
152  if (1 == nLayers) {
153  return allValidSets;
154  }
155  MuonRecHitContainer validSet;
156  unsigned int iPos0 = 0;
157  std::vector<unsigned int> iLayer(12); // could there be more than 11 layers?
158  std::vector<unsigned int> size(12);
159  if (iPos0 < nLayers) {
160  size.at(iPos0) = MuonRecHitContainer_perLayer.at(iPos0).size();
161  for (iLayer[iPos0] = 0; iLayer[iPos0] < size[iPos0]; ++iLayer[iPos0]) {
162  validSet.clear();
163  validSet.push_back(MuonRecHitContainer_perLayer[iPos0][iLayer[iPos0]]);
164  unsigned int iPos1 = 1;
165  if (iPos1 < nLayers) {
166  size.at(iPos1) = MuonRecHitContainer_perLayer.at(iPos1).size();
167  for (iLayer[iPos1] = 0; iLayer[iPos1] < size[iPos1]; ++iLayer[iPos1]) {
168  validSet.resize(iPos1);
169  validSet.push_back(MuonRecHitContainer_perLayer[iPos1][iLayer[iPos1]]);
170  unsigned int iPos2 = 2;
171  if (iPos2 < nLayers) {
172  size.at(iPos2) = MuonRecHitContainer_perLayer.at(iPos2).size();
173  for (iLayer[iPos2] = 0; iLayer[iPos2] < size[iPos2]; ++iLayer[iPos2]) {
174  validSet.resize(iPos2);
175  validSet.push_back(MuonRecHitContainer_perLayer[iPos2][iLayer[iPos2]]);
176  unsigned int iPos3 = 3;
177  if (iPos3 < nLayers) {
178  size.at(iPos3) = MuonRecHitContainer_perLayer.at(iPos3).size();
179  for (iLayer[iPos3] = 0; iLayer[iPos3] < size[iPos3]; ++iLayer[iPos3]) {
180  validSet.resize(iPos3);
181  validSet.push_back(MuonRecHitContainer_perLayer[iPos3][iLayer[iPos3]]);
182  unsigned int iPos4 = 4;
183  if (iPos4 < nLayers) {
184  size.at(iPos4) = MuonRecHitContainer_perLayer.at(iPos4).size();
185  for (iLayer[iPos4] = 0; iLayer[iPos4] < size[iPos4]; ++iLayer[iPos4]) {
186  validSet.resize(iPos4);
187  validSet.push_back(MuonRecHitContainer_perLayer[iPos4][iLayer[iPos4]]);
188  unsigned int iPos5 = 5;
189  if (iPos5 < nLayers) {
190  size.at(iPos5) = MuonRecHitContainer_perLayer.at(iPos5).size();
191  for (iLayer[iPos5] = 0; iLayer[iPos5] < size[iPos5]; ++iLayer[iPos5]) {
192  validSet.resize(iPos5);
193  validSet.push_back(MuonRecHitContainer_perLayer[iPos5][iLayer[iPos5]]);
194  unsigned int iPos6 = 6;
195  if (iPos6 < nLayers) {
196  size.at(iPos6) = MuonRecHitContainer_perLayer.at(iPos6).size();
197  for (iLayer[iPos6] = 0; iLayer[iPos6] < size[iPos6]; ++iLayer[iPos6]) {
198  validSet.resize(iPos6);
199  validSet.push_back(MuonRecHitContainer_perLayer[iPos6][iLayer[iPos6]]);
200  unsigned int iPos7 = 7;
201  if (iPos7 < nLayers) {
202  size.at(iPos7) = MuonRecHitContainer_perLayer.at(iPos7).size();
203  for (iLayer[iPos7] = 0; iLayer[iPos7] < size[iPos7]; ++iLayer[iPos7]) {
204  validSet.resize(iPos7);
205  validSet.push_back(MuonRecHitContainer_perLayer[iPos7][iLayer[iPos7]]);
206  unsigned int iPos8 = 8;
207  if (iPos8 < nLayers) {
208  size.at(iPos8) = MuonRecHitContainer_perLayer.at(iPos8).size();
209  for (iLayer[iPos8] = 0; iLayer[iPos8] < size[iPos8]; ++iLayer[iPos8]) {
210  validSet.resize(iPos8);
211  validSet.push_back(MuonRecHitContainer_perLayer[iPos8][iLayer[iPos8]]);
212  unsigned int iPos9 = 9;
213  if (iPos9 < nLayers) {
214  size.at(iPos9) = MuonRecHitContainer_perLayer.at(iPos9).size();
215  for (iLayer[iPos9] = 0; iLayer[iPos9] < size[iPos9]; ++iLayer[iPos9]) {
216  validSet.resize(iPos9);
217  validSet.push_back(MuonRecHitContainer_perLayer[iPos9][iLayer[iPos9]]);
218  unsigned int iPos10 = 10;
219  if (iPos10 < nLayers) {
220  size.at(iPos10) = MuonRecHitContainer_perLayer.at(iPos10).size();
221  for (iLayer[iPos10] = 0; iLayer[iPos10] < size[iPos10]; ++iLayer[iPos10]) {
222  validSet.resize(iPos10);
223  validSet.push_back(MuonRecHitContainer_perLayer[iPos10][iLayer[iPos10]]);
224  unsigned int iPos11 = 11; // more?
225  if (iPos11 < nLayers) {
226  size.at(iPos11) = MuonRecHitContainer_perLayer.at(iPos11).size();
227  for (iLayer[iPos11] = 0; iLayer[iPos11] < size[iPos11];
228  ++iLayer[iPos11]) {
229  }
230  } else {
231  allValidSets.push_back(validSet);
232  }
233  }
234  } else {
235  allValidSets.push_back(validSet);
236  }
237  }
238  } else {
239  allValidSets.push_back(validSet);
240  }
241  }
242  } else {
243  allValidSets.push_back(validSet);
244  }
245  }
246  } else {
247  allValidSets.push_back(validSet);
248  }
249  }
250  } else {
251  allValidSets.push_back(validSet);
252  }
253  }
254  } else {
255  allValidSets.push_back(validSet);
256  }
257  }
258  } else {
259  allValidSets.push_back(validSet);
260  }
261  }
262  } else {
263  allValidSets.push_back(validSet);
264  }
265  }
266  } else {
267  allValidSets.push_back(validSet);
268  }
269  }
270  } else {
271  allValidSets.push_back(validSet);
272  }
273  }
274  } else {
275  allValidSets.push_back(validSet);
276  }
277  return allValidSets;
278 }
279 
280 std::pair<int, int> // or <bool, bool>
281 SETSeedFinder::checkAngleDeviation(double dPhi_1, double dPhi_2) const {
282  // Two conditions:
283  // a) deviations should be only to one side (above some absolute value cut to avoid
284  // material effects; this should be refined)
285  // b) deviatiation in preceding steps should be bigger due to higher magnetic field
286  // (again - a minimal value cut should be in place; this also should account for
287  // the small (Z) distances in overlaping CSC chambers)
288 
289  double mult = dPhi_1 * dPhi_2;
290  int signVal = 1;
291  if (fabs(dPhi_1) < fabs(dPhi_2)) {
292  signVal = -1;
293  }
294  int signMult = -1;
295  if (mult > 0)
296  signMult = 1;
297  std::pair<int, int> sign;
298  sign = make_pair(signVal, signMult);
299 
300  return sign;
301 }
302 
303 void SETSeedFinder::validSetsPrePruning(std::vector<SETSeedFinder::MuonRecHitContainer>& allValidSets) {
304  //---- this actually is a pre-pruning; it does not include any fit information;
305  //---- it is intended to remove only very "wild" segments from a set;
306  //---- no "good" segment is to be lost (otherwise - widen the parameters)
307 
308  for (unsigned int iSet = 0; iSet < allValidSets.size(); ++iSet) {
309  pre_prune(allValidSets[iSet]);
310  }
311 }
312 
314  unsigned nHits = validSet.size();
315  if (nHits > 3) { // to decide we need at least 4 measurements
316  // any information could be used to make a decision for pruning
317  // maybe dPhi (delta Phi) is enough
318  std::vector<double> dPhi;
319  double dPhi_tmp;
320  bool wildCandidate;
321  int pruneHit_tmp;
322 
323  for (unsigned int iHit = 1; iHit < nHits; ++iHit) {
324  dPhi_tmp = validSet[iHit]->globalPosition().phi() - validSet[iHit - 1]->globalPosition().phi();
325  dPhi.push_back(dPhi_tmp);
326  }
327  std::vector<int> pruneHit;
328  //---- loop over all the hits in a set
329 
330  for (unsigned int iHit = 0; iHit < nHits; ++iHit) {
331  double dPHI_MIN = 0.02; //?? hardcoded - remove it
332  if (iHit) {
333  // if we have to remove the very first hit (iHit == 0) then
334  // we'll probably be in trouble already
335  wildCandidate = false;
336  // actually 2D is bad only if not r-phi... Should I refine it?
337  // a hit is a candidate for pruning only if dPhi > dPHI_MIN;
338  // pruning decision is based on combination of hits characteristics
339  if (4 == validSet[iHit - 1]->dimension() && 4 == validSet[iHit]->dimension() &&
340  fabs(validSet[iHit]->globalPosition().phi() - validSet[iHit - 1]->globalPosition().phi()) > dPHI_MIN) {
341  wildCandidate = true;
342  }
343  pruneHit_tmp = -1;
344  if (wildCandidate) {
345  // OK - this couple doesn't look good (and is from 4D segments); proceed...
346  if (1 == iHit) { // the first and the last hits are special case
347  if (4 == validSet[iHit + 1]->dimension() && 4 == validSet[iHit + 2]->dimension()) { //4D?
348  // is the picture better if we remove the second hit?
349  dPhi_tmp = validSet[iHit + 1]->globalPosition().phi() - validSet[iHit - 1]->globalPosition().phi();
350  // is the deviation what we expect (sign, not magnitude)?
351  std::pair<int, int> sign = checkAngleDeviation(dPhi_tmp, dPhi[2]);
352  if (1 == sign.first && 1 == sign.second) {
353  pruneHit_tmp = iHit; // mark the hit 1 for removing
354  }
355  }
356  } else if (iHit > 1 && iHit < validSet.size() - 1) {
357  if (4 == validSet[0]->dimension() && // we rely on the first (most important) couple
358  4 == validSet[1]->dimension() && pruneHit.back() != int(iHit - 1) &&
359  pruneHit.back() != 1) { // check if hits are already marked
360  // decide which of the two hits should be removed (if any; preferably the outer one i.e.
361  // iHit rather than iHit-1); here - check what we get by removing iHit
362  dPhi_tmp = validSet[iHit + 1]->globalPosition().phi() - validSet[iHit - 1]->globalPosition().phi();
363  // first couple is most important anyway so again compare to it
364  std::pair<int, int> sign = checkAngleDeviation(dPhi[0], dPhi_tmp);
365  if (1 == sign.first && 1 == sign.second) {
366  pruneHit_tmp = iHit; // mark the hit iHit for removing
367  } else { // iHit is not to be removed; proceed...
368  // what if we remove (iHit - 1) instead of iHit?
369  dPhi_tmp = validSet[iHit + 1]->globalPosition().phi() - validSet[iHit]->globalPosition().phi();
370  std::pair<int, int> sign = checkAngleDeviation(dPhi[0], dPhi_tmp);
371  if (1 == sign.first && 1 == sign.second) {
372  pruneHit_tmp = iHit - 1; // mark the hit (iHit -1) for removing
373  }
374  }
375  }
376  } else {
377  // the last hit: if picture is not good - remove it
378  if (pruneHit.size() > 1 && pruneHit[pruneHit.size() - 1] < 0 && pruneHit[pruneHit.size() - 2] < 0) {
379  std::pair<int, int> sign = checkAngleDeviation(dPhi[dPhi.size() - 2], dPhi[dPhi.size() - 1]);
380  if (-1 == sign.first && -1 == sign.second) { // here logic is a bit twisted
381  pruneHit_tmp = iHit; // mark the last hit for removing
382  }
383  }
384  }
385  }
386  pruneHit.push_back(pruneHit_tmp);
387  }
388  }
389  // }
390  // actual pruning
391  for (unsigned int iHit = 1; iHit < nHits; ++iHit) {
392  int count = 0;
393  if (pruneHit[iHit - 1] > 0) {
394  validSet.erase(validSet.begin() + pruneHit[iHit - 1] - count);
395  ++count;
396  }
397  }
398  }
399 }
400 
401 std::vector<SeedCandidate> SETSeedFinder::fillSeedCandidates(std::vector<MuonRecHitContainer>& allValidSets) {
402  //---- we have the valid sets constructed; transform the information in an
403  //---- apropriate form; meanwhile - estimate the momentum for a given set
404 
405  // RPCs should not be used (no parametrization)
406  std::vector<SeedCandidate> seedCandidates_inCluster;
407  // calculate and fill the inputs needed
408  // loop over all valid sets
409  for (unsigned int iSet = 0; iSet < allValidSets.size(); ++iSet) {
410  //
411  //std::cout<<" This is SET number : "<<iSet<<std::endl;
412  //for(unsigned int iHit = 0;iHit<allValidSets[iSet].size();++iHit){
413  //std::cout<<" measurements in the SET: iHit = "<<iHit<<" pos = "<<allValidSets[iSet][iHit]->globalPosition()<<
414  //" dim = "<<allValidSets[iSet][iHit]->dimension()<<std::endl;
415  //}
416 
417  CLHEP::Hep3Vector momEstimate;
418  int chargeEstimate;
419  estimateMomentum(allValidSets[iSet], momEstimate, chargeEstimate);
420  MuonRecHitContainer MuonRecHitContainer_theSet_prep;
421  // currently hardcoded - will be in proper loop of course:
422 
423  SeedCandidate seedCandidates_inCluster_prep;
424  seedCandidates_inCluster_prep.theSet = allValidSets[iSet];
425  seedCandidates_inCluster_prep.momentum = momEstimate;
426  seedCandidates_inCluster_prep.charge = chargeEstimate;
427  seedCandidates_inCluster.push_back(seedCandidates_inCluster_prep);
428  // END estimateMomentum
429  }
430  return seedCandidates_inCluster;
431 }
432 
434  CLHEP::Hep3Vector& momEstimate,
435  int& charge) const {
436  int firstMeasurement = -1;
437  int lastMeasurement = -1;
438 
439  // don't use 2D measurements for momentum estimation
440 
441  //if( 4==allValidSets[iSet].front()->dimension() &&
442  //(allValidSets[iSet].front()->isCSC() || allValidSets[iSet].front()->isDT())){
443  //firstMeasurement = 0;
444  //}
445  //else{
446  // which is the "first" hit (4D)?
447  for (unsigned int iMeas = 0; iMeas < validSet.size(); ++iMeas) {
448  if (4 == validSet[iMeas]->dimension() && (validSet[iMeas]->isCSC() || validSet[iMeas]->isDT())) {
449  firstMeasurement = iMeas;
450  break;
451  }
452  }
453  //}
454 
455  std::vector<double> momentum_estimate;
456  double pT = 0.;
459  // which is the second hit?
460  for (int loop = 0; loop < 2; ++loop) { // it is actually not used; to be removed
461  // this is the last measurement
462  if (!loop) { // this is what is used currently
463  // 23.04.09 : it becomes a problem with introduction of ME42 chambers -
464  // the initial pT parametrization is incorrect for them
465  for (int iMeas = validSet.size() - 1; iMeas > -1; --iMeas) {
466  if (4 == validSet[iMeas]->dimension() && (validSet[iMeas]->isCSC() || validSet[iMeas]->isDT()) &&
467  // below is a fix saying "don't use ME4 chambers for initial pT estimation";
468  // not using ME41 should not be a big loss too (and is more "symmetric" solution)
469  fabs(validSet[iMeas]->globalPosition().z()) < 1000.) {
470  lastMeasurement = iMeas;
471  break;
472  }
473  }
474  } else {
475  // this is the second measurement
476  for (unsigned int iMeas = 1; iMeas < validSet.size(); ++iMeas) {
477  if (4 == validSet[iMeas]->dimension() && (validSet[iMeas]->isCSC() || validSet[iMeas]->isDT())) {
478  lastMeasurement = iMeas;
479  break;
480  }
481  }
482  }
483  // only 2D measurements (it should have been already abandoned)
484  if (-1 == lastMeasurement && -1 == firstMeasurement) {
485  firstMeasurement = 0;
486  lastMeasurement = validSet.size() - 1;
487  }
488  // because of the ME42 above lastMeasurement could be -1
489  else if (-1 == lastMeasurement) {
490  lastMeasurement = firstMeasurement;
491  } else if (-1 == firstMeasurement) {
492  firstMeasurement = lastMeasurement;
493  }
494 
495  firstHit = validSet[firstMeasurement];
496  secondHit = validSet[lastMeasurement];
497  if (firstHit->isRPC() && secondHit->isRPC()) { // remove all RPCs from here?
498  momentum_estimate.push_back(300.);
499  momentum_estimate.push_back(300.);
500  } else {
501  if (firstHit->isRPC()) {
502  firstHit = secondHit;
503  } else if (secondHit->isRPC()) {
504  secondHit = firstHit;
505  }
506  //---- estimate pT given two hits
507  //std::cout<<" hits for initial pT estimate: first -> dim = "<<firstHit->dimension()<<" pos = "<<firstHit->globalPosition()<<
508  //" , second -> "<<" dim = "<<secondHit->dimension()<<" pos = "<<secondHit->globalPosition()<<std::endl;
509  //---- pT throws exception if hits are MB4
510  // (no coding for them - 2D hits in the outer station)
511  if (2 == firstHit->dimension() && 2 == secondHit->dimension()) {
512  momentum_estimate.push_back(999999999.);
513  momentum_estimate.push_back(999999999.);
514  } else {
515  momentum_estimate = thePtExtractor->pT_extract(firstHit, secondHit);
516  }
517  }
518  pT = fabs(momentum_estimate[0]);
519  if (true || pT > 40.) { //it is skipped; we have to look at least into number of hits in the chamber actually...
520  // and then decide which segment to use
521  // use the last measurement, otherwise use the second; this is to be investigated
522  break;
523  }
524  }
525 
526  const float pT_min = 1.99; // many hardcoded - remove them!
527  if (pT > 3000.) {
528  pT = 3000.;
529  } else if (pT < pT_min) {
530  if (pT > 0) {
531  pT = pT_min;
532  } else if (pT > (-1) * pT_min) {
533  pT = (-1) * pT_min;
534  } else if (pT < -3000.) {
535  pT = -3000;
536  }
537  }
538  //std::cout<<" THE pT from the parametrization: "<<momentum_estimate[0]<<std::endl;
539  // estimate the charge of the track candidate from the delta phi of two segments:
540  //int charge = dPhi > 0 ? 1 : -1; // what we want is: dphi < 0 => charge = -1
541  charge = momentum_estimate[0] > 0 ? 1 : -1;
542 
543  // we have the pT - get the 3D momentum estimate as well
544 
545  // this is already final info:
546  double xHit = validSet[firstMeasurement]->globalPosition().x();
547  double yHit = validSet[firstMeasurement]->globalPosition().y();
548  double rHit = TMath::Sqrt(pow(xHit, 2) + pow(yHit, 2));
549 
550  double thetaInner = validSet[firstMeasurement]->globalPosition().theta();
551  // if some of the segments is missing r-phi measurement then we should
552  // use only the 4D phi estimate (also use 4D eta estimate only)
553  // the direction is not so important (it will be corrected)
554 
555  double rTrack = (pT / (0.3 * 3.8)) * 100.; //times 100 for conversion to cm!
556 
557  double par = -1. * (2. / charge) * (TMath::ASin(rHit / (2 * rTrack)));
558  double sinPar = TMath::Sin(par);
559  double cosPar = TMath::Cos(par);
560 
561  // calculate phi at coordinate origin (0,0,0).
562  double sinPhiH = 1. / (2. * charge * rTrack) * (xHit + ((sinPar) / (cosPar - 1.)) * yHit);
563  double cosPhiH = -1. / (2. * charge * rTrack) * (((sinPar) / (1. - cosPar)) * xHit + yHit);
564 
565  // finally set the return vector
566 
567  // try out the reco info:
568  // should used into to theta directly here (rather than tan(atan2(...)))
569  momEstimate = CLHEP::Hep3Vector(pT * cosPhiH, pT * sinPhiH, pT / TMath::Tan(thetaInner));
570  //Hep3Vector momEstimate(6.97961, 5.89732, -50.0855);
571  const float minMomenum = 5.; //hardcoded - remove it! same in SETFilter
572  if (momEstimate.mag() < minMomenum) {
573  int sign = (pT < 0.) ? -1 : 1;
574  pT = sign * (fabs(pT) + 1);
575  CLHEP::Hep3Vector momEstimate2(pT * cosPhiH, pT * sinPhiH, pT / TMath::Tan(thetaInner));
576  momEstimate = momEstimate2;
577  if (momEstimate.mag() < minMomenum) {
578  pT = sign * (fabs(pT) + 1);
579  CLHEP::Hep3Vector momEstimate3(pT * cosPhiH, pT * sinPhiH, pT / TMath::Tan(thetaInner));
580  momEstimate = momEstimate3;
581  if (momEstimate.mag() < minMomenum) {
582  pT = sign * (fabs(pT) + 1);
583  CLHEP::Hep3Vector momEstimate4(pT * cosPhiH, pT * sinPhiH, pT / TMath::Tan(thetaInner));
584  momEstimate = momEstimate4;
585  }
586  }
587  }
588 }
589 
592  edm::OwnVector<TrackingRecHit> recHitsContainer;
593  for (unsigned int iHit = 0; iHit < hits.size(); ++iHit) {
594  recHitsContainer.push_back(hits.at(iHit)->hit()->clone());
595  }
598  dir = alongMomentum; // why forward (for rechits) later?
599  }
600 
601  PTrajectoryStateOnDet const& seedTSOS =
602  trajectoryStateTransform::persistentState(firstTSOS, hits.at(0)->geographicalId().rawId());
603  TrajectorySeed seed(seedTSOS, recHitsContainer, dir);
604 
605  //MuonPatternRecoDumper debug;
606  //std::cout<<" firstTSOS = "<<debug.dumpTSOS(firstTSOS)<<std::endl;
607  //std::cout<<" iTraj = ???"<<" hits = "<<range.second-range.first<<std::endl;
608  //std::cout<<" nhits = "<<hits.size()<<std::endl;
609  //for(unsigned int iRH=0;iRH<hits.size();++iRH){
610  //std::cout<<" RH = "<<iRH+1<<" globPos = "<<hits.at(iRH)->globalPosition()<<std::endl;
611  //}
612  return seed;
613 }
size
Write out results.
int station() const
Return the station number.
Definition: DTChamberId.h:42
bool operator()(TransientTrackingRecHit::ConstRecHitPointer hit_1, TransientTrackingRecHit::ConstRecHitPointer hit_2) const
Definition: SETFilter.cc:34
T getParameter(std::string const &) const
Definition: ParameterSet.h:307
bool apply_prePruning
Definition: SETSeedFinder.h:55
CLHEP::Hep3Vector momentum
Definition: SETFilter.h:35
std::pair< int, int > checkAngleDeviation(double dPhi_1, double dPhi_2) const
PTrajectoryStateOnDet persistentState(const TrajectoryStateOnSurface &ts, unsigned int detid)
constexpr int pow(int x)
Definition: conifer.h:24
bool useSegmentsInTrajectory
Definition: SETSeedFinder.h:56
PropagationDirection
bool isDT(GeomDetEnumerators::SubDetector m)
ParameterSet const & parameterSet(StableProvenance const &provenance, ProcessHistory const &history)
Definition: Provenance.cc:11
sorter()
Definition: SETFilter.cc:33
void push_back(D *&d)
Definition: OwnVector.h:326
std::shared_ptr< MuonTransientTrackingRecHit > MuonRecHitPointer
const string metname
constexpr int subdetId() const
get the contents of the subdetector field (not cast into any detector&#39;s numbering enum) ...
Definition: DetId.h:48
MuonTransientTrackingRecHit::MuonRecHitContainer MuonRecHitContainer
Definition: SETSeedFinder.h:13
void pre_prune(MuonRecHitContainer &validSet) const
std::vector< ConstRecHitPointer > ConstRecHitContainer
MuonSeedPtExtractor * thePtExtractor
void limitCombinatorics(std::vector< MuonRecHitContainer > &MuonRecHitContainer_perLayer)
float localZ(const GlobalPoint &gp) const
Definition: Plane.h:45
Definition: DetId.h:17
std::vector< MuonRecHitContainer > sortByLayer(MuonRecHitContainer &cluster) const
const Plane & surface() const
The nominal surface of the GeomDet.
Definition: GeomDet.h:37
T mag() const
The vector magnitude. Equivalent to sqrt(vec.mag2())
int station() const
Definition: CSCDetId.h:79
void seeds(const MuonRecHitContainer &cluster, std::vector< TrajectorySeed > &result) override
std::vector< MuonRecHitContainer > findAllValidSets(const std::vector< MuonRecHitContainer > &MuonRecHitContainer_perLayer)
MuonServiceProxy * theService
Definition: SETSeedFinder.h:53
HLT enums.
void validSetsPrePruning(std::vector< MuonRecHitContainer > &allValidSets)
virtual std::vector< double > pT_extract(MuonTransientTrackingRecHit::ConstMuonRecHitPointer firstHit, MuonTransientTrackingRecHit::ConstMuonRecHitPointer secondHit) const
bool isCSC(GeomDetEnumerators::SubDetector m)
MuonTransientTrackingRecHit::MuonRecHitContainer theSet
Definition: SETFilter.h:34
TrajectorySeed makeSeed(const TrajectoryStateOnSurface &tsos, const TransientTrackingRecHit::ConstRecHitContainer &hits) const
std::shared_ptr< MuonTransientTrackingRecHit const > ConstMuonRecHitPointer
static constexpr int DT
Definition: MuonSubdetId.h:11
int ring() const
Definition: CSCDetId.h:68
std::vector< SeedCandidate > fillSeedCandidates(std::vector< MuonRecHitContainer > &allValidSets)
TupleMultiplicity< TrackerTraits > const *__restrict__ uint32_t nHits
uint32_t dimension(pat::CandKinResolution::Parametrization parametrization)
Returns the number of free parameters in a parametrization (3 or 4)
static constexpr int CSC
Definition: MuonSubdetId.h:12
void estimateMomentum(const MuonRecHitContainer &validSet, CLHEP::Hep3Vector &momentum, int &charge) const
SETSeedFinder(const edm::ParameterSet &pset)