CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
DTMeantimerPatternReco.cc
Go to the documentation of this file.
1 
8 /* This Class Header */
10 
11 /* Collaborating Class Header */
26 
27 /* C++ Headers */
28 #include <iterator>
29 using namespace std;
31 
32 /* ====================================================================== */
33 
34  typedef std::vector<std::shared_ptr<DTHitPairForFit>> hitCont;
35  typedef hitCont::const_iterator hitIter;
36 
37 
41  theFitter(new DTLinearFit()),
42  theAlgoName("DTMeantimerPatternReco")
43 {
44  theMaxAllowedHits = pset.getParameter<unsigned int>("MaxAllowedHits"); // 100
45  theAlphaMaxTheta = pset.getParameter<double>("AlphaMaxTheta");// 0.1 ;
46  theAlphaMaxPhi = pset.getParameter<double>("AlphaMaxPhi");// 1.0 ;
47  theMaxChi2 = pset.getParameter<double>("MaxChi2");// 8.0 ;
48  debug = pset.getUntrackedParameter<bool>("debug");
49  theUpdator = new DTSegmentUpdator(pset);
50  theCleaner = new DTSegmentCleaner(pset);
51 }
52 
55  delete theUpdator;
56  delete theCleaner;
57  delete theFitter;
58 }
59 
60 /* Operations */
63  const std::vector<DTRecHit1DPair>& pairs){
64 
66  std::vector<std::shared_ptr<DTHitPairForFit>> hitsForFit = initHits(sl, pairs);
67 
68  vector<DTSegmentCand*> candidates = buildSegments(sl, hitsForFit);
69 
70  vector<DTSegmentCand*>::const_iterator cand=candidates.begin();
71  while (cand<candidates.end()) {
72 
73  DTSLRecSegment2D *segment = (**cand);
74  theUpdator->update(segment,1);
75 
76  if (debug) cout<<"Reconstructed 2D segments "<<*segment<<endl;
77  result.push_back(segment);
78 
79  delete *(cand++); // delete the candidate!
80  }
81 
82  return result;
83 }
84 
86  // Get the DT Geometry
87  setup.get<MuonGeometryRecord>().get(theDTGeometry);
88  theUpdator->setES(setup);
89 }
90 
91 vector<std::shared_ptr<DTHitPairForFit>>
93  const std::vector<DTRecHit1DPair>& hits){
94 
96  for (vector<DTRecHit1DPair>::const_iterator hit=hits.begin();
97  hit!=hits.end(); ++hit) {
98  result.push_back(std::make_shared<DTHitPairForFit>(*hit, *sl, theDTGeometry));
99  }
100  return result;
101 }
102 
103 vector<DTSegmentCand*>
105  const std::vector<std::shared_ptr<DTHitPairForFit>>& hits){
106 
107  vector<DTSegmentCand*> result;
109 
110  if(debug) {
111  cout << "buildSegments: " << sl->id() << " nHits " << hits.size() << endl;
112  for (hitIter hit=hits.begin(); hit!=hits.end(); ++hit) cout << **hit<< " wire: " << (*hit)->id() << " DigiTime: " << (*hit)->digiTime() << endl;
113  }
114 
115  if (hits.size() > theMaxAllowedHits ) {
116  if(debug) {
117  cout << "Warning: this SuperLayer " << sl->id() << " has too many hits : "
118  << hits.size() << " max allowed is " << theMaxAllowedHits << endl;
119  cout << "Skipping segment reconstruction... " << endl;
120  }
121  return result;
122  }
123 
124  GlobalPoint IP;
125  float DAlphaMax;
126  if ((sl->id()).superlayer()==2) // Theta SL
127  DAlphaMax=theAlphaMaxTheta;
128  else // Phi SL
129  DAlphaMax=theAlphaMaxPhi;
130 
131  // get two hits in different layers and see if there are other hits
132  // compatible with them
133  for (hitCont::const_iterator firstHit=hits.begin(); firstHit!=hits.end();
134  ++firstHit) {
135  for (hitCont::const_reverse_iterator lastHit=hits.rbegin();
136  (*lastHit)!=(*firstHit); ++lastHit) {
137 
138  // a geometrical sensibility cut for the two hits
139  if (!geometryFilter((*firstHit)->id(),(*lastHit)->id())) continue;
140 
141  // create a set of hits for the fit (only the hits between the two selected ones)
142  hitCont hitsForFit;
143  for (hitCont::const_iterator tmpHit=firstHit+1; (*tmpHit)!=(*lastHit); tmpHit++)
144  if ((geometryFilter((*tmpHit)->id(),(*lastHit)->id()))
145  && (geometryFilter((*tmpHit)->id(),(*firstHit)->id()))) hitsForFit.push_back(*tmpHit);
146 
147  for (int firstLR=0; firstLR<2; ++firstLR) {
148  for (int lastLR=0; lastLR<2; ++lastLR) {
149 
150  // TODO move the global transformation in the DTHitPairForFit class
151  // when it will be moved I will able to remove the sl from the input parameter
152  GlobalPoint gposFirst=sl->toGlobal( (*firstHit)->localPosition(codes[firstLR]) );
153  GlobalPoint gposLast= sl->toGlobal( (*lastHit)->localPosition(codes[lastLR]) );
154  GlobalVector gvec=gposLast-gposFirst;
155  GlobalVector gvecIP=gposLast-IP;
156 
157  // difference in angle measured
158  float DAlpha=fabs(gvec.theta()-gvecIP.theta());
159  if (DAlpha>DAlphaMax) continue;
160 
161 // if(debug) {
162 // cout << "Selected hit pair:" << endl;
163 // cout << " First " << *(*firstHit) << " Layer Id: " << (*firstHit)->id().layerId() << " Side: " << firstLR << " DigiTime: " << (*firstHit)->digiTime() << endl;
164 // cout << " Last " << *(*lastHit) << " Layer Id: " << (*lastHit)->id().layerId() << " Side: " << lastLR << " DigiTime: " << (*lastHit)->digiTime() << endl;
165 // }
166 
168  std::unique_ptr<DTSegmentCand> segCand(new DTSegmentCand(pointSet,sl));
169  segCand->add(*firstHit,codes[firstLR]);
170  segCand->add(*lastHit,codes[lastLR]);
171 
172  // run hit adding/segment building
173  maxfound = 3;
174  addHits(segCand.get(),hitsForFit,result);
175  }
176  }
177  }
178  }
179 
180  // now I have a couple of segment hypotheses, should check for ghosts
181  if (debug) {
182  cout << "Result (before cleaning): " << result.size() << endl;
183  for (vector<DTSegmentCand*>::const_iterator seg=result.begin(); seg!=result.end(); ++seg) cout << *(*seg) << endl;
184  }
185 
186  result = theCleaner->clean(result);
187 
188  if (debug) {
189  cout << "Result (after cleaning): " << result.size() << endl;
190  for (vector<DTSegmentCand*>::const_iterator seg=result.begin(); seg!=result.end(); ++seg) cout << *(*seg) << endl;
191  }
192 
193  return result;
194 }
195 
196 void
197 DTMeantimerPatternReco::addHits(DTSegmentCand* segCand, const vector<std::shared_ptr<DTHitPairForFit>>& hits,
198  vector<DTSegmentCand*> &result) {
199 
200  double chi2l,chi2r,t0l,t0r;
201  bool foundSomething = false;
202 
203  if (debug)
204  cout << " DTMeantimerPatternReco::addHit " << endl << " Picked " << segCand->nHits() << " hits, " << hits.size() << " left." << endl;
205 
206  if (segCand->nHits()+hits.size()<maxfound) return;
207 
208  // loop over the remaining hits
209  for (hitCont::const_iterator hit=hits.begin(); hit!=hits.end(); ++hit) {
210 
211 // if (debug) {
212 // cout << " Trying B: " << **hit<< " wire: " << (*hit)->id() << endl;
213 // printPattern(assHits,*hit);
214 // }
215 
218 
219  segCand->add(lhit);
220  bool left_ok=(fitWithT0(segCand,0)?true:false);
221  chi2l=segCand->chi2();
222  t0l=segCand->t0();
223  segCand->removeHit(lhit);
224 
225  segCand->add(rhit);
226  bool right_ok=(fitWithT0(segCand,0)?true:false);
227  chi2r=segCand->chi2();
228  t0r=segCand->t0();
229  segCand->removeHit(rhit);
230 
231  if (debug) {
232  int nHits=segCand->nHits()+1;
233  cout << " Left: t0= " << t0l << " chi2/nHits= " << chi2l << "/" << nHits << " ok: " << left_ok << endl;
234  cout << " Right: t0= " << t0r << " chi2/nHits= " << chi2r << "/" << nHits << " ok: " << right_ok << endl;
235  }
236 
237  if (!left_ok && !right_ok) continue;
238 
239  foundSomething = true;
240 
241  // prepare the hit set for the next search, start from the other side
242  hitCont hitsForFit;
243  for (hitCont::const_iterator tmpHit=hit+1; tmpHit!=hits.end(); tmpHit++)
244  if (geometryFilter((*tmpHit)->id(),(*hit)->id())) hitsForFit.push_back(*tmpHit);
245 
246  reverse(hitsForFit.begin(),hitsForFit.end());
247 
248  // choose only one - left or right
249  if (segCand->nHits()>3 && left_ok && right_ok) {
250  if (chi2l<chi2r-0.1) right_ok=false; else
251  if (chi2r<chi2l-0.1) left_ok=false;
252  }
253 
254  if (left_ok) {
255  segCand->add(lhit);
256  addHits(segCand,hitsForFit,result);
257  segCand->removeHit(lhit);
258  }
259 
260  if (right_ok) {
261  segCand->add(rhit);
262  addHits(segCand,hitsForFit,result);
263  segCand->removeHit(rhit);
264  }
265  }
266 
267  if (foundSomething) return;
268  // if we didn't find any new hits compatible with the current candidate, we proceed to check and store the candidate
269 
270  // If we already have a segment with more hits from this hit pair - don't save this one.
271  if (segCand->nHits()<maxfound) return;
272 
273  // Check if semgent Ok, calculate chi2
274  bool seg_ok=(fitWithT0(segCand,debug)?true:false);
275  if (!seg_ok) return;
276 
277  if (!segCand->good()) {
278 // if (debug) cout << " Segment not good() - skipping" << endl;
279  return;
280  }
281 
282  if (segCand->nHits()>maxfound) maxfound = segCand->nHits();
283  if (debug) cout << endl << " Seg t0= " << segCand->t0() << endl << *segCand << endl;
284 
285  if (checkDoubleCandidates(result,segCand)) {
286  result.push_back(new DTSegmentCand(*segCand));
287  if (debug) cout << " Result is now " << result.size() << endl;
288  } else {
289  if (debug) cout << " Exists - skipping" << endl;
290  }
291 }
292 
293 
294 bool
296 {
297 // return true;
298 
299  const int layerLowerCut[4]={0,-1,-2,-2};
300  const int layerUpperCut[4]={0, 2, 2, 3};
301 // const int layerLowerCut[4]={0,-2,-4,-5};
302 // const int layerUpperCut[4]={0, 3, 4, 6};
303 
304  // deal only with hits that are in the same SL
305  if (first.layerId().superlayerId().superLayer()!=second.layerId().superlayerId().superLayer())
306  return true;
307 
308  int deltaLayer=abs(first.layerId().layer()-second.layerId().layer());
309 
310  // drop hits in the same layer
311  if (!deltaLayer) return false;
312 
313  // protection against unexpected layer numbering
314  if (deltaLayer>3) {
315  cout << "*** WARNING! DT Layer numbers differ by more than 3! for hits: " << endl;
316  cout << " " << first << endl;
317  cout << " " << second << endl;
318  return false;
319  }
320 
321  // accept only hits in cells "not too far away"
322  int deltaWire=first.wire()-second.wire();
323  if (second.layerId().layer()%2==0) deltaWire=-deltaWire; // yet another trick to get it right...
324  if ((deltaWire<=layerLowerCut[deltaLayer]) || (deltaWire>=layerUpperCut[deltaLayer])) return false;
325 
326  return true;
327 }
328 
329 
332 {
333  // perform the 3 parameter fit on the segment candidate
334  theUpdator->fit(seg,1,fitdebug);
335  double chi2=seg->chi2();
336 
337  // Sanity check - drop segment candidates with a failed 3-par fit.
338  // (this includes segments with hits after the calculated t0 correction ending up
339  // beyond the chamber walls or on the other side of the wire)
340  if (chi2==-1.) return nullptr;
341 
342  // at this point we keep all 3-hit segments that passed the above check
343  if (seg->nHits()==3) return seg;
344 
345  // for segments with no t0 information we impose a looser chi2 cut
346  if (seg->t0()==0) {
347  if (chi2<100.) return seg;
348  else return nullptr;
349  }
350 
351  // cut on chi2/ndof of the segment candidate
352  if ((chi2/(seg->nHits()-3)<theMaxChi2)) return seg;
353  else return nullptr;
354 }
355 
356 
357 
358 bool
359 DTMeantimerPatternReco::checkDoubleCandidates(vector<DTSegmentCand*>& cands,
360  DTSegmentCand* seg) {
361  for (vector<DTSegmentCand*>::iterator cand=cands.begin();
362  cand!=cands.end(); ++cand) {
363  if (*(*cand)==*seg) return false;
364  if (((*cand)->nHits()>=seg->nHits()) && ((*cand)->chi2ndof()<seg->chi2ndof()))
365  if ((*cand)->nSharedHitPairs(*seg)>int(seg->nHits()-2)) return false;
366  }
367  return true;
368 }
369 
370 
371 
372 void
373 DTMeantimerPatternReco::printPattern( vector<DTSegmentCand::AssPoint>& assHits, const DTHitPairForFit* hit) {
374 
375  char mark[26]={". . . . . . . . . . . . "};
376  int wire[12]={0,0,0,0,0,0,0,0,0,0,0,0};
377 
378  for (vector<DTSegmentCand::AssPoint>::const_iterator assHit=assHits.begin(); assHit!=assHits.end(); ++assHit) {
379  int lay = (((*assHit).first)->id().superlayerId().superLayer()-1)*4 + ((*assHit).first)->id().layerId().layer()-1;
380  wire[lay]= ((*assHit).first)->id().wire();
381  if ((*assHit).second==DTEnums::Left) mark[lay*2]='L'; else mark[lay*2]='R';
382  }
383 
384  int lay = ((*hit).id().superlayerId().superLayer()-1)*4 + (*hit).id().layerId().layer() - 1;
385  wire[lay]= (*hit).id().wire();
386  mark[lay*2]='*';
387 
388  cout << " " << mark << endl << " ";
389  for (int i=0; i<12; i++) if (wire[i]) cout << setw(2) << wire[i]; else cout << " ";
390  cout << endl;
391 }
std::pair< std::shared_ptr< DTHitPairForFit >, DTEnums::DTCellSide > AssPoint
Definition: DTSegmentCand.h:38
std::vector< std::shared_ptr< DTHitPairForFit > > initHits(const DTSuperLayer *sl, const std::vector< DTRecHit1DPair > &hits)
T getParameter(std::string const &) const
T getUntrackedParameter(std::string const &, T const &) const
int i
Definition: DBlmapReader.cc:9
virtual double chi2ndof() const
the chi2/NDOF of the fit
Definition: DTSegmentCand.h:67
bool checkDoubleCandidates(std::vector< DTSegmentCand * > &segs, DTSegmentCand *seg)
void addHits(DTSegmentCand *segCand, const std::vector< std::shared_ptr< DTHitPairForFit >> &hits, std::vector< DTSegmentCand * > &result)
GlobalPoint toGlobal(const Local2DPoint &lp) const
Conversion to the global R.F. from the R.F. of the GeomDet.
Definition: GeomDet.h:52
DTCellSide
Which side of the DT cell.
Definition: DTEnums.h:15
virtual ~DTMeantimerPatternReco()
Destructor.
int layer() const
Return the layer number.
Definition: DTLayerId.h:53
std::vector< DTSegmentCand * > clean(const std::vector< DTSegmentCand * > &inputCands) const
do the cleaning
DTSuperLayerId superlayerId() const
Return the corresponding SuperLayerId.
Definition: DTLayerId.h:59
virtual bool good() const
std::vector< std::shared_ptr< DTHitPairForFit > > hitCont
tuple result
Definition: mps_fire.py:95
Geom::Theta< T > theta() const
Definition: PV3DBase.h:75
U second(std::pair< T, U > const &p)
DTSuperLayerId id() const
Return the DetId of this SL.
Definition: DTSuperLayer.cc:36
DTSegmentCand * fitWithT0(DTSegmentCand *seg, const bool fitdebug)
void push_back(D *&d)
Definition: OwnVector.h:290
std::vector< DTSegmentCand * > buildSegments(const DTSuperLayer *sl, const std::vector< std::shared_ptr< DTHitPairForFit >> &hits)
virtual void setES(const edm::EventSetup &setup)
void setES(const edm::EventSetup &setup)
set the setup
virtual void add(AssPoint newHit)
add hits to the hit list.
tuple IP
Definition: listHistos.py:76
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
int superLayer() const
Return the superlayer number.
int mark
Definition: cuy.py:1009
virtual double chi2() const
the chi2 (NOT chi2/NDOF) of the fit
Definition: DTSegmentCand.h:64
unsigned int id
int wire() const
Return the wire number.
Definition: DTWireId.h:56
void printPattern(std::vector< DTSegmentCand::AssPoint > &assHits, const DTHitPairForFit *hit)
std::set< AssPoint, AssPointLessZ > AssPointCont
Definition: DTSegmentCand.h:40
virtual unsigned int nHits() const
Definition: DTSegmentCand.h:61
hitCont::const_iterator hitIter
virtual double t0() const
the t0 of the segment
Definition: DTSegmentCand.h:70
const T & get() const
Definition: EventSetup.h:56
bool geometryFilter(const DTWireId first, const DTWireId second) const
virtual edm::OwnVector< DTSLRecSegment2D > reconstruct(const DTSuperLayer *sl, const std::vector< DTRecHit1DPair > &hits)
this function is called in the producer
DTLayerId layerId() const
Return the corresponding LayerId.
Definition: DTWireId.h:62
DTMeantimerPatternReco(const edm::ParameterSet &pset)
Constructor.
virtual void removeHit(AssPoint hit)
remove hit from the candidate
tuple cout
Definition: gather_cfg.py:145
void update(DTRecSegment4D *seg, const bool calcT0, bool allow3par) const
recompute hits position and refit the segment4D
void setup(std::vector< TH2F > &depth, std::string name, std::string units="")
bool fit(DTSegmentCand *seg, bool allow3par, const bool fitdebug) const
edm::ESHandle< DTGeometry > theDTGeometry