CMS 3D CMS Logo

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