CMS 3D CMS Logo

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