CMS 3D CMS Logo

MuonShowerInformationFiller.cc
Go to the documentation of this file.
1 
13 
14 // system include files
15 #include <memory>
16 #include <algorithm>
17 #include <iostream>
18 
19 // user include files
52 
55 
61 
62 using namespace std;
63 using namespace edm;
64 
65 //
66 // Constructor
67 //
69  theService(nullptr),
70  theDTRecHitLabel(par.getParameter<InputTag>("DTRecSegmentLabel")),
71  theCSCRecHitLabel(par.getParameter<InputTag>("CSCRecSegmentLabel")),
72  theCSCSegmentsLabel(par.getParameter<InputTag>("CSCSegmentLabel")),
73  theDT4DRecSegmentLabel(par.getParameter<InputTag>("DT4DRecSegmentLabel"))
74 {
75 
80 
81 
82  edm::ParameterSet serviceParameters = par.getParameter<edm::ParameterSet>("ServiceParameters");
83  theService = new MuonServiceProxy(serviceParameters);
84 
85  theTrackerRecHitBuilderName = par.getParameter<string>("TrackerRecHitBuilder");
86  theMuonRecHitBuilderName = par.getParameter<string>("MuonRecHitBuilder");
87 
88  theCacheId_TRH = 0;
89  theCacheId_MT = 0;
90 
91  category_ = "MuonShowerInformationFiller";
92 
93  for (int istat = 0; istat < 4; istat++) {
94  theStationShowerDeltaR.push_back(0.);
95  theStationShowerTSize.push_back(0.);
96  theAllStationHits.push_back(0);
97  theCorrelatedStationHits.push_back(0);
98  }
99 
100 }
101 
102 //
103 // Destructor
104 //
106  if (theService) delete theService;
107 }
108 
109 //
110 //Fill the MuonShower struct
111 //
113 
114  reco::MuonShower returnShower;
115 
116  // Update the services
117  theService->update(iSetup);
118  setEvent(iEvent);
119  setServices(theService->eventSetup());
120 
121  fillHitsByStation(muon);
122  std::vector<int> nStationHits = theAllStationHits;
123  std::vector<int> nStationCorrelatedHits = theCorrelatedStationHits;
124  std::vector<float> stationShowerSizeT = theStationShowerTSize;
125  std::vector<float> stationShowerDeltaR = theStationShowerDeltaR;
126 
127  returnShower.nStationHits = nStationHits;
128  returnShower.nStationCorrelatedHits = nStationCorrelatedHits;
129  returnShower.stationShowerSizeT = stationShowerSizeT;
130  returnShower.stationShowerDeltaR = stationShowerDeltaR;
131 
132  return returnShower;
133 
134 }
135 
136 //
137 // Set Event
138 //
140 
141  // get all the necesary products
142  event.getByToken(theDTRecHitToken, theDTRecHits);
143  event.getByToken(theCSCRecHitToken, theCSCRecHits);
144  event.getByToken(theCSCSegmentsToken, theCSCSegments);
145  event.getByToken(theDT4DRecSegmentToken, theDT4DRecSegments);
146 
147  for (int istat = 0; istat < 4; istat++) {
148  theStationShowerDeltaR.at(istat) = 0.;
149  theStationShowerTSize.at(istat) = 0.;
150  theAllStationHits.at(istat) = 0;
151  theCorrelatedStationHits.at(istat) = 0;
152  }
153 }
154 
155 
156 //
157 // Set services
158 //
160 
161  // DetLayer Geometry
163  setup.get<IdealMagneticFieldRecord>().get(theField);
165  setup.get<MuonGeometryRecord>().get(theCSCGeometry);
166  setup.get<MuonGeometryRecord>().get(theDTGeometry);
167 
168  // Transient Rechit Builders
169  unsigned long long newCacheId_TRH = setup.get<TransientRecHitRecord>().cacheIdentifier();
170  if ( newCacheId_TRH != theCacheId_TRH ) {
173  }
174 
175 }
176 
177 //
178 // Get hits owned by segments
179 //
184 
186 
187  DetId geoId = geomDet->geographicalId();
188 
189  if (geoId.subdetId() == MuonSubdetId::DT) {
190 
191  DTChamberId chamberId(geoId.rawId());
192 
193  // loop on segments 4D
194  DTRecSegment4DCollection::id_iterator chamberIdIt;
195  for (chamberIdIt = dtSegments->id_begin();
196  chamberIdIt != dtSegments->id_end();
197  ++chamberIdIt){
198 
199  if (*chamberIdIt != chamberId) continue;
200 
201  // Get the range for the corresponding ChamberId
202  DTRecSegment4DCollection::range range = dtSegments->get((*chamberIdIt));
203 
204  for (DTRecSegment4DCollection::const_iterator iseg = range.first;
205  iseg!=range.second;++iseg) {
206  if (iseg->dimension() != 4) continue;
207  segments.push_back(MuonTransientTrackingRecHit::specificBuild(geomDet,&*iseg));
208  }
209  }
210  }
211  else if (geoId.subdetId() == MuonSubdetId::CSC) {
212 
213  CSCDetId did(geoId.rawId());
214 
215  for ( CSCSegmentCollection::id_iterator chamberId = cscSegments->id_begin();
216  chamberId != cscSegments->id_end(); ++chamberId) {
217 
218  if ((*chamberId).chamber() != did.chamber()) continue;
219 
220  // Get the range for the corresponding ChamberId
221  CSCSegmentCollection::range range = cscSegments->get((*chamberId));
222 
223  for (CSCSegmentCollection::const_iterator iseg = range.first;
224  iseg!=range.second;++iseg) {
225  if (iseg->dimension() != 3) continue;
226  segments.push_back(MuonTransientTrackingRecHit::specificBuild(geomDet,&*iseg));
227  }
228  }
229  }
230  else {
231  LogTrace(category_) << "Segments are not built in RPCs" << endl;
232  }
233 
235 
236  if (segments.empty()) return allhitscorrelated;
237 
238  TransientTrackingRecHit::ConstRecHitPointer muonRecHit(segments.front());
239  allhitscorrelated = MuonTransientTrackingRecHitBreaker::breakInSubRecHits(muonRecHit,2);
240 
241  if (segments.size() == 1) return allhitscorrelated;
242 
243  for (MuonTransientTrackingRecHit::MuonRecHitContainer::const_iterator iseg = segments.begin() + 1;
244  iseg != segments.end(); ++iseg) {
245 
248 
249  for (TransientTrackingRecHit::ConstRecHitContainer::const_iterator ihit1 = hits1.begin();
250  ihit1 != hits1.end(); ++ihit1 ) {
251 
252  bool usedbefore = false;
253  //unused DetId thisID = (*ihit1)->geographicalId();
254  //LocalPoint lp1dinsegHit = (*ihit1)->localPosition();
255  GlobalPoint gp1dinsegHit = (*ihit1)->globalPosition();
256 
257  for (TransientTrackingRecHit::ConstRecHitContainer::const_iterator ihit2 = allhitscorrelated.begin();
258  ihit2 != allhitscorrelated.end(); ++ihit2 ) {
259 
260  //unused DetId thisID2 = (*ihit2)->geographicalId();
261  //LocalPoint lp1dinsegHit2 = (*ihit2)->localPosition();
262  GlobalPoint gp1dinsegHit2 = (*ihit2)->globalPosition();
263 
264  if ( (gp1dinsegHit2 - gp1dinsegHit).mag() < 1.0 ) usedbefore = true;
265 
266  }
267  if ( !usedbefore ) allhitscorrelated.push_back(*ihit1);
268  }
269  }
270 
271  return allhitscorrelated;
272 
273 }
274 
275 
276 //
277 // Find cluster
278 //
279 
282  const GlobalPoint& refpoint) const {
283 
284  if ( muonRecHits.empty() ) return muonRecHits;
285 
286  //clustering step by theta
287  float step = 0.05;
289 
290  stable_sort(muonRecHits.begin(), muonRecHits.end(), AbsLessDTheta(refpoint));
291 
292  for (TransientTrackingRecHit::ConstRecHitContainer::const_iterator ihit = muonRecHits.begin(); ihit != muonRecHits.end() - 1; ++ihit) {
293  if (fabs((*(ihit+1))->globalPosition().theta() - (*ihit)->globalPosition().theta() ) < step) {
294  result.push_back(*ihit);
295  } else {
296  break;
297  }
298  }
299 
300  return result;
301 
302 }
303 
304 //
305 //Used to treat overlap region
306 //
309 
310  if ( muonRecHits.empty() ) return muonRecHits;
311 
312  stable_sort(muonRecHits.begin(), muonRecHits.end(), LessPerp());
313 
314  MuonTransientTrackingRecHit::MuonRecHitContainer::const_iterator
315  seedhit = min_element(muonRecHits.begin(), muonRecHits.end(), LessPerp());
316 
317  MuonTransientTrackingRecHit::MuonRecHitContainer::const_iterator ihigh = seedhit;
318  MuonTransientTrackingRecHit::MuonRecHitContainer::const_iterator ilow = seedhit;
319 
320  float step = 0.1;
321  while (ihigh != muonRecHits.end()-1 && ( fabs((*(ihigh+1))->globalPosition().perp() - (*ihigh)->globalPosition().perp() ) < step) ) {
322  ihigh++;
323  }
324  while (ilow != muonRecHits.begin() && ( fabs((*ilow)->globalPosition().perp() - (*(ilow -1))->globalPosition().perp()) < step ) ) {
325  ilow--;
326  }
327 
329 
330  return result;
331 
332 }
333 
334 //
335 // Get compatible dets
336 //
338 
339  vector<const GeomDet*> total;
340  total.reserve(1000);
341 
342  LogTrace(category_) << "Consider a track " << track.p() << " eta: " << track.eta() << " phi " << track.phi() << endl;
343 
344 
345  TrajectoryStateOnSurface innerTsos = trajectoryStateTransform::innerStateOnSurface(track, *theService->trackingGeometry(), &*theService->magneticField());
346  TrajectoryStateOnSurface outerTsos = trajectoryStateTransform::outerStateOnSurface(track, *theService->trackingGeometry(), &*theService->magneticField());
347 
348  GlobalPoint innerPos = innerTsos.globalPosition();
349  GlobalPoint outerPos = outerTsos.globalPosition();
350 
351  vector<GlobalPoint> allCrossingPoints;
352 
353  const vector<const DetLayer*>& dtlayers = theService->detLayerGeometry()->allDTLayers();
354 
355  for (auto iLayer = dtlayers.begin(); iLayer != dtlayers.end(); ++iLayer) {
356 
357  // crossing points of track with cylinder
358  GlobalPoint xPoint = crossingPoint(innerPos, outerPos, dynamic_cast<const BarrelDetLayer*>(*iLayer));
359 
360  // check if point is inside the detector
361  if ((fabs(xPoint.y()) < 1000.0) && (fabs(xPoint.z()) < 1500 ) &&
362  (!(xPoint.y() == 0 && xPoint.x() == 0 && xPoint.z() == 0))) allCrossingPoints.push_back(xPoint);
363  }
364 
365  stable_sort(allCrossingPoints.begin(), allCrossingPoints.end(), LessMag(innerPos) );
366 
367  vector<const GeomDet*> tempDT;
368 
369  for (vector<GlobalPoint>::const_iterator ipos = allCrossingPoints.begin(); ipos != allCrossingPoints.end(); ++ipos) {
370 
371  tempDT = dtPositionToDets(*ipos);
372  vector<const GeomDet*>::const_iterator begin = tempDT.begin();
373  vector<const GeomDet*>::const_iterator end = tempDT.end();
374 
375  for (; begin!=end;++begin) {
376  total.push_back(*begin);
377  }
378 
379  }
380  allCrossingPoints.clear();
381 
382  const vector<const DetLayer*>& csclayers = theService->detLayerGeometry()->allCSCLayers();
383  for (auto iLayer = csclayers.begin(); iLayer != csclayers.end(); ++iLayer) {
384 
385  GlobalPoint xPoint = crossingPoint(innerPos, outerPos, dynamic_cast<const ForwardDetLayer*>(*iLayer));
386 
387  // check if point is inside the detector
388  if ((fabs(xPoint.y()) < 1000.0) && (fabs(xPoint.z()) < 1500.0)
389  && (!(xPoint.y() == 0 && xPoint.x() == 0 && xPoint.z() == 0))) allCrossingPoints.push_back(xPoint);
390  }
391  stable_sort(allCrossingPoints.begin(), allCrossingPoints.end(), LessMag(innerPos) );
392 
393  vector<const GeomDet*> tempCSC;
394  for (vector<GlobalPoint>::const_iterator ipos = allCrossingPoints.begin(); ipos != allCrossingPoints.end(); ++ipos) {
395 
396  tempCSC = cscPositionToDets(*ipos);
397  vector<const GeomDet*>::const_iterator begin = tempCSC.begin();
398  vector<const GeomDet*>::const_iterator end = tempCSC.end();
399 
400  for (; begin!=end;++begin) {
401  total.push_back(*begin);
402  }
403 
404  }
405 
406  return total;
407 
408 }
409 
410 
411 //
412 // Intersection point of track with barrel layer
413 //
415  const GlobalPoint& p2,
416  const BarrelDetLayer* dl) const {
417 
418  const BoundCylinder& bc = dl->specificSurface();
419  return crossingPoint(p1, p2, bc);
420 
421 }
422 
424  const GlobalPoint& p2,
425  const Cylinder& cyl) const {
426 
427  float radius = cyl.radius();
428 
429  GlobalVector dp = p1 - p2;
430  float slope = dp.x()/dp.y();
431  float a = p1.x() - slope * p1.y();
432 
433  float n2 = (1 + slope * slope);
434  float n1 = 2*a*slope;
435  float n0 = a*a - radius*radius;
436 
437  float y1 = 9999;
438  float y2 = 9999;
439  if ( n1*n1 - 4*n2*n0 > 0 ) {
440  y1 = (-n1 + sqrt(n1*n1 - 4*n2*n0) ) / (2 * n2);
441  y2 = (-n1 - sqrt(n1*n1 - 4*n2*n0) ) / (2 * n2);
442  }
443 
444  float x1 = p1.x() + slope * (y1 - p1.y());
445  float x2 = p1.x() + slope * (y2 - p1.y());
446 
447  float slopeZ = dp.z()/dp.y();
448 
449  float z1 = p1.z() + slopeZ * (y1 - p1.y());
450  float z2 = p1.z() + slopeZ * (y2 - p1.y());
451 
452  // there are two crossing points, return the one that is in the same quadrant as point of extrapolation
453  if ((p2.x()*x1 > 0) && (y1*p2.y() > 0) && (z1*p2.z() > 0)) {
454  return GlobalPoint(x1, y1, z1);
455  } else {
456  return GlobalPoint(x2, y2, z2);
457  }
458 
459 }
460 
461 
462 //
463 // Intersection point of track with a forward layer
464 //
466  const GlobalPoint& p2,
467  const ForwardDetLayer* dl) const {
468 
469  const BoundDisk& bc = dl->specificSurface();
470  return crossingPoint(p1, p2, bc);
471 
472 }
473 
475  const GlobalPoint& p2,
476  const BoundDisk& disk) const {
477 
478  float diskZ = disk.position().z();
479  int endcap = diskZ > 0 ? 1 : (diskZ < 0 ? -1 : 0);
480  diskZ = diskZ + endcap*dynamic_cast<const SimpleDiskBounds&>(disk.bounds()).thickness()/2.;
481 
482  GlobalVector dp = p1 - p2;
483 
484  float slopeZ = dp.z()/dp.y();
485  float y1 = diskZ / slopeZ;
486 
487  float slopeX = dp.z()/dp.x();
488  float x1 = diskZ / slopeX;
489 
490  float z1 = diskZ;
491 
492  if (p2.z()*z1 > 0) {
493  return GlobalPoint(x1, y1, z1);
494  } else {
495  return GlobalPoint(0, 0, 0);
496  }
497 
498 }
499 
500 
501 //
502 // GeomDets along the track in DT
503 //
504 vector<const GeomDet*> MuonShowerInformationFiller::dtPositionToDets(const GlobalPoint& gp) const {
505 
506  int minwheel = -3;
507  int maxwheel = -3;
508  if ( gp.z() < -680.0 ) { minwheel = -3; maxwheel = -3;}
509  else if ( gp.z() < -396.0 ) { minwheel = -2; maxwheel = -1;}
510  else if (gp.z() < -126.8) { minwheel = -2; maxwheel = 0; }
511  else if (gp.z() < 126.8) { minwheel = -1; maxwheel = 1; }
512  else if (gp.z() < 396.0) { minwheel = 0; maxwheel = 2; }
513  else if (gp.z() < 680.0) { minwheel = 1; maxwheel = 2; }
514  else { minwheel = 3; maxwheel = 3; }
515 
516  int station = 5;
517  if ( gp.perp() > 680.0 && gp.perp() < 755.0 ) station = 4;
518  else if ( gp.perp() > 580.0 ) station = 3;
519  else if ( gp.perp() > 480.0 ) station = 2;
520  else if ( gp.perp() > 380.0 ) station = 1;
521  else station = 0;
522 
523  vector<int> sectors;
524 
525  float phistep = M_PI/6;
526 
527  float phigp = (float)gp.barePhi();
528 
529  if ( fabs(deltaPhi(phigp, 0*phistep)) < phistep ) sectors.push_back(1);
530  if ( fabs(deltaPhi(phigp, phistep)) < phistep ) sectors.push_back(2);
531  if ( fabs(deltaPhi(phigp, 2*phistep)) < phistep ) sectors.push_back(3);
532  if ( fabs(deltaPhi(phigp, 3*phistep)) < phistep ) {
533  sectors.push_back(4);
534  if (station == 4) sectors.push_back(13);
535  }
536  if ( fabs(deltaPhi(phigp, 4*phistep)) < phistep ) sectors.push_back(5);
537  if ( fabs(deltaPhi(phigp, 5*phistep)) < phistep ) sectors.push_back(6);
538  if ( fabs(deltaPhi(phigp, 6*phistep)) < phistep ) sectors.push_back(7);
539  if ( fabs(deltaPhi(phigp, 7*phistep)) < phistep ) sectors.push_back(8);
540  if ( fabs(deltaPhi(phigp, 8*phistep)) < phistep ) sectors.push_back(9);
541  if ( fabs(deltaPhi(phigp, 9*phistep)) < phistep ) {
542  sectors.push_back(10);
543  if (station == 4) sectors.push_back(14);
544  }
545  if ( fabs(deltaPhi(phigp, 10*phistep)) < phistep ) sectors.push_back(11);
546  if ( fabs(deltaPhi(phigp, 11*phistep)) < phistep ) sectors.push_back(12);
547 
548  LogTrace(category_) << "DT position to dets" << endl;
549  LogTrace(category_) << "number of sectors to consider: " << sectors.size() << endl;
550  LogTrace(category_) << "station: " << station << " wheels: " << minwheel << " " << maxwheel << endl;
551 
552  vector<const GeomDet*> result;
553  if (station > 4 || station < 1) return result;
554  if (minwheel > 2 || maxwheel < -2) return result;
555 
556  for (vector<int>::const_iterator isector = sectors.begin(); isector != sectors.end(); ++isector ) {
557  for (int iwheel = minwheel; iwheel != maxwheel + 1; ++iwheel) {
558  DTChamberId chamberid(iwheel, station, (*isector));
559  result.push_back(theService->trackingGeometry()->idToDet(chamberid));
560  }
561  }
562 
563  LogTrace(category_) << "number of GeomDets for this track: " << result.size() << endl;
564 
565  return result;
566 
567 }
568 
569 
570 //
571 // GeomDets along the track in CSC
572 //
573 vector<const GeomDet*> MuonShowerInformationFiller::cscPositionToDets(const GlobalPoint& gp) const {
574 
575  // determine the endcap side
576  int endcap = 0;
577  if (gp.z() > 0) {endcap = 1;} else {endcap = 2;}
578 
579  // determine the csc station and range of rings
580  int station = 5;
581 
582  // check all rings in a station
583  if ( fabs(gp.z()) > 1000. && fabs(gp.z()) < 1055.0 ) {
584  station = 4;
585  }
586  else if ( fabs(gp.z()) > 910.0 && fabs(gp.z()) < 965.0) {
587  station = 3;
588  }
589  else if ( fabs(gp.z()) > 800.0 && fabs(gp.z()) < 860.0) {
590  station = 2;
591  }
592  else if ( fabs(gp.z()) > 570.0 && fabs(gp.z()) < 730.0) {
593  station = 1;
594  }
595 
596  vector<int> sectors;
597 
598  float phistep1 = M_PI/18.; //for all the rings except first rings for stations > 1
599  float phistep2 = M_PI/9.;
600  float phigp = (float)gp.barePhi();
601 
602  int ring = -1;
603 
604  // determine the ring
605  if (station == 1) {
606 
607 //FIX ME!!!
608  if (gp.perp() > 100 && gp.perp() < 270) ring = 1;
609  else if (gp.perp() > 270 && gp.perp() < 450) ring = 2;
610  else if (gp.perp() > 450 && gp.perp() < 695) ring = 3;
611  else if (gp.perp() > 100 && gp.perp() < 270) ring = 4;
612 
613  }
614  else if (station == 2) {
615 
616  if (gp.perp() > 140 && gp.perp() < 350) ring = 1;
617  else if (gp.perp() > 350 && gp.perp() < 700) ring = 2;
618 
619  }
620  else if (station == 3) {
621 
622  if (gp.perp() > 160 && gp.perp() < 350) ring = 1;
623  else if (gp.perp() > 350 && gp.perp() < 700) ring = 2;
624 
625  }
626  else if (station == 4) {
627 
628  if (gp.perp() > 175 && gp.perp() < 350) ring = 1;
629  else if (gp.perp() > 350 && gp.perp() < 700) ring = 2;
630 
631  }
632 
633  if (station > 1 && ring == 1) {
634 
635  // we have 18 sectors in that case
636  for (int i = 0; i < 18; i++) {
637  if ( fabs(deltaPhi(phigp, i*phistep2)) < phistep2 ) sectors.push_back(i+1);
638  }
639 
640  } else {
641 
642  // we have 36 sectors in that case
643  for (int i = 0; i < 36; i++) {
644  if ( fabs(deltaPhi(phigp, i*phistep1)) < phistep1 ) sectors.push_back(i+1);
645  }
646 }
647 
648  LogTrace(category_) << "CSC position to dets" << endl;
649  LogTrace(category_) << "ring: " << ring << endl;
650  LogTrace(category_) << "endcap: " << endcap << endl;
651  LogTrace(category_) << "station: " << station << endl;
652  LogTrace(category_) << "CSC number of sectors to consider: " << sectors.size() << endl;
653 
654 
655  // check exceptional cases
656  vector<const GeomDet*> result;
657  if (station > 4 || station < 1) return result;
658  if (endcap == 0) return result;
659  if (ring == -1) return result;
660 
661  int minlayer = 1;
662  int maxlayer = 6;
663 
664  for (vector<int>::const_iterator isector = sectors.begin(); isector != sectors.end(); ++isector) {
665  for (int ilayer = minlayer; ilayer != maxlayer + 1; ++ ilayer) {
666  CSCDetId cscid(endcap, station, ring, (*isector), ilayer);
667  result.push_back(theService->trackingGeometry()->idToDet(cscid));
668  }
669  }
670 
671  return result;
672 
673 }
674 
675 //
676 //Set class members
677 //
679 
681  if ( muon.isGlobalMuon() ) track = muon.globalTrack();
682  else if ( muon.isStandAloneMuon() ) track = muon.outerTrack();
683  else return;
684 
685  // split 1D rechits by station
686  vector<MuonRecHitContainer> muonRecHits(4);
687 
688  // split rechits from segs by station
689  vector<TransientTrackingRecHit::ConstRecHitContainer> muonCorrelatedHits(4);
690 
691  // get vector of GeomDets compatible with a track
692  vector<const GeomDet*> compatibleLayers = getCompatibleDets(*track);
693 
694  // for special cases: CSC station 1
695  MuonRecHitContainer tmpCSC1;
696  bool dtOverlapToCheck = false;
697  bool cscOverlapToCheck = false;
698 
699  for (vector<const GeomDet*>::const_iterator igd = compatibleLayers.begin(); igd != compatibleLayers.end(); igd++ ) {
700 
701  // get det id
702  DetId geoId = (*igd)->geographicalId();
703 
704  // skip tracker hits
705  if (geoId.det()!= DetId::Muon) continue;
706 
707  // DT
708  if ( geoId.subdetId() == MuonSubdetId::DT ) {
709 
710  // get station
711  DTChamberId detid(geoId.rawId());
712  int station = detid.station();
713  int wheel = detid.wheel();
714 
715  // get rechits from segments per station
717  TransientTrackingRecHit::ConstRecHitContainer::const_iterator hits_begin = muonCorrelatedHitsTmp.begin();
718  TransientTrackingRecHit::ConstRecHitContainer::const_iterator hits_end = muonCorrelatedHitsTmp.end();
719 
720  for (; hits_begin!= hits_end;++hits_begin) {
721  muonCorrelatedHits.at(station-1).push_back(*hits_begin);
722  }
723 
724  //check overlap certain wheels and stations
725  if (abs(wheel) == 2 && station != 4 && station != 1) dtOverlapToCheck = true;
726 
727  // loop over all superlayers of a DT chamber
728  for (int isuperlayer = DTChamberId::minSuperLayerId; isuperlayer != DTChamberId::maxSuperLayerId + 1; ++isuperlayer) {
729  // loop over all layers inside the superlayer
730  for (int ilayer = DTChamberId::minLayerId; ilayer != DTChamberId::maxLayerId+1; ++ilayer) {
731  DTLayerId lid(detid, isuperlayer, ilayer);
732  DTRecHitCollection::range dRecHits = theDTRecHits->get(lid);
733  for (DTRecHitCollection::const_iterator rechit = dRecHits.first; rechit != dRecHits.second;++rechit) {
734  vector<const TrackingRecHit*> subrechits = (*rechit).recHits();
735  for (vector<const TrackingRecHit*>::iterator irechit = subrechits.begin(); irechit != subrechits.end(); ++irechit) {
736  muonRecHits.at(station-1).push_back(MuonTransientTrackingRecHit::specificBuild((&**igd),&**irechit));
737  }
738  }
739  }
740  }
741  }
742  else if (geoId.subdetId() == MuonSubdetId::CSC) {
743 
744  // get station
745  CSCDetId did(geoId.rawId());
746  int station = did.station();
747  int ring = did.ring();
748 
749  //get rechits from segments by station
751  TransientTrackingRecHit::ConstRecHitContainer::const_iterator hits_begin = muonCorrelatedHitsTmp.begin();
752  TransientTrackingRecHit::ConstRecHitContainer::const_iterator hits_end = muonCorrelatedHitsTmp.end();
753 
754  for (; hits_begin!= hits_end;++hits_begin) {
755  muonCorrelatedHits.at(station-1).push_back(*hits_begin);
756  }
757 
758  if ((station == 1 && ring == 3) && dtOverlapToCheck) cscOverlapToCheck = true;
759 
760  // split 1D rechits by station
761  CSCRecHit2DCollection::range dRecHits = theCSCRecHits->get(did);
762  for (CSCRecHit2DCollection::const_iterator rechit = dRecHits.first; rechit != dRecHits.second; ++rechit) {
763 
764  if (!cscOverlapToCheck) {
765  muonRecHits.at(station-1).push_back(MuonTransientTrackingRecHit::specificBuild((&**igd),&*rechit));
766  } else {
767  tmpCSC1.push_back(MuonTransientTrackingRecHit::specificBuild((&**igd),&*rechit));
768 
769  //sort by perp, then insert to appropriate container
771  if (temp.empty()) continue;
772 
773  float center;
774  if (temp.size() > 1) {
775  center = (temp.front()->globalPosition().perp() + temp.back()->globalPosition().perp())/2.;
776  } else {
777  center = temp.front()->globalPosition().perp();
778  }
779  temp.clear();
780 
781  if (center > 550.) {
782  muonRecHits.at(2).insert(muonRecHits.at(2).end(),tmpCSC1.begin(),tmpCSC1.end());
783  } else {
784  muonRecHits.at(1).insert(muonRecHits.at(1).end(),tmpCSC1.begin(),tmpCSC1.end());
785  }
786  tmpCSC1.clear();
787  }
788  }
789  } else if (geoId.subdetId() == MuonSubdetId::RPC) {
790  LogTrace(category_) << "Wrong subdet id" << endl;
791  }
792  }//loop over GeomDets compatible with a track
793 
794  // calculate number of all and correlated hits
795  for (int stat = 0; stat < 4; stat++) {
796  theCorrelatedStationHits[stat] = muonCorrelatedHits.at(stat).size();
797  theAllStationHits[stat] = muonRecHits[stat].size();
798  }
799  LogTrace(category_) << "Hits used by the segments, by station "
800  << theCorrelatedStationHits.at(0) << " "
801  << theCorrelatedStationHits.at(1) << " "
802  << theCorrelatedStationHits.at(2) << " "
803  << theCorrelatedStationHits.at(3) << endl;
804 
805  LogTrace(category_) << "All DT 1D/CSC 2D hits, by station "
806  << theAllStationHits.at(0) << " "
807  << theAllStationHits.at(1) << " "
808  << theAllStationHits.at(2) << " "
809  << theAllStationHits.at(3) << endl;
810 
811  //station shower sizes
813  TransientTrackingRecHit::ConstRecHitContainer muonRecHitsThetaTemp, muonRecHitsThetaBest;
814  // send station hits to the clustering algorithm
815  for ( int stat = 0; stat != 4; stat++ ) {
816  const size_t nhit = muonRecHits[stat].size();
817  if (nhit < 2) continue; // Require at least 2 hits
818  muonRecHitsPhiBest.clear();
819  muonRecHitsPhiBest.reserve(nhit);
820 
821  // Cluster seeds by global position phi. Best cluster is chosen to give greatest dphi
822  // Sort by phi (complexity = NLogN with enough memory, or = NLog^2N for insufficient mem)
823  stable_sort(muonRecHits[stat].begin(), muonRecHits[stat].end(), LessPhi());
824 
825  // Search for gaps (complexity = N)
826  std::vector<size_t> clUppers;
827  for ( size_t ihit = 0; ihit < nhit; ++ihit ) {
828  const size_t jhit = (ihit+1)%nhit;
829  const double phi1 = muonRecHits[stat].at(ihit)->globalPosition().barePhi();
830  const double phi2 = muonRecHits[stat].at(jhit)->globalPosition().barePhi();
831 
832  const double dphi = std::abs(deltaPhi(phi1, phi2));
833  if ( dphi >= 0.05 ) clUppers.push_back(ihit);
834  }
835 
836  //station shower sizes
837  double dphimax = 0;
838  if ( clUppers.empty() ) {
839  // No gaps - there is only one cluster. Take all of them
840  const double refPhi = muonRecHits[stat].at(0)->globalPosition().barePhi();
841  double dphilo = 0, dphihi = 0;
842  for ( auto& hit : muonRecHits[stat] ) {
843  muonRecHitsPhiBest.push_back(hit);
844  const double phi = hit->globalPosition().barePhi();
845  dphilo = std::min(dphilo, deltaPhi(refPhi, phi));
846  dphihi = std::max(dphihi, deltaPhi(refPhi, phi));
847  }
848  dphimax = std::abs(dphihi+dphilo);
849  } else {
850  // Loop over gaps to find the one with maximum dphi(begin, end)
851  // By construction, number of gap must be greater than 1.
852  size_t bestUpper = 0, bestLower = 0;
853  for ( auto icl = clUppers.begin(); icl != clUppers.end(); ++icl ) {
854  // upper bound of this cluster
855  const size_t upper = *icl;
856  // lower bound is +1 of preceeding upper bound
857  const auto prevCl = (icl == clUppers.begin()) ? clUppers.end() : icl;
858  const size_t lower = (*(prevCl-1)+1)%nhit;
859 
860  // At least two hit for a cluster
861  if ( upper == lower ) continue;
862 
863  const double phi1 = muonRecHits[stat].at(upper)->globalPosition().barePhi();
864  const double phi2 = muonRecHits[stat].at(lower)->globalPosition().barePhi();
865 
866  const double dphi = std::abs(deltaPhi(phi1, phi2));
867  if ( dphimax < dphi ) {
868  dphimax = dphi;
869  bestUpper = upper;
870  bestLower = lower;
871  }
872  }
873 
874  if ( bestUpper > bestLower ) {
875  muonRecHitsPhiBest.reserve(bestUpper-bestLower+1);
876  std::copy(muonRecHits[stat].begin()+bestLower,
877  muonRecHits[stat].begin()+bestUpper+1,
878  std::back_inserter(muonRecHitsPhiBest));
879  } else if ( bestUpper < bestLower ) {
880  muonRecHitsPhiBest.reserve(bestUpper+(nhit-bestLower)+1);
881  std::copy(muonRecHits[stat].begin(),
882  muonRecHits[stat].begin()+bestUpper+1,
883  std::back_inserter(muonRecHitsPhiBest));
884  std::copy(muonRecHits[stat].begin()+bestLower,
885  muonRecHits[stat].end(),
886  std::back_inserter(muonRecHitsPhiBest));
887  }
888  }
889 
890  //fill showerTs
891  if (!muonRecHitsPhiBest.empty()) {
892  muonRecHits[stat] = muonRecHitsPhiBest;
893  stable_sort(muonRecHits[stat].begin(), muonRecHits[stat].end(), LessAbsMag());
894  muonRecHits[stat].front();
895  GlobalPoint refpoint = muonRecHits[stat].front()->globalPosition();
896  theStationShowerTSize.at(stat) = refpoint.mag() * dphimax;
897  }
898 
899  //for theta
900  if (!muonCorrelatedHits.at(stat).empty()) {
901 
902  float dthetamax = 0;
903  for (TransientTrackingRecHit::ConstRecHitContainer::const_iterator iseed = muonCorrelatedHits.at(stat).begin(); iseed != muonCorrelatedHits.at(stat).end(); ++iseed) {
904  if (!(*iseed)->isValid()) continue;
905  GlobalPoint refpoint = (*iseed)->globalPosition(); //starting from the one with smallest value of phi
906  muonRecHitsThetaTemp.clear();
907  muonRecHitsThetaTemp = findThetaCluster(muonCorrelatedHits.at(stat), refpoint);
908  if (muonRecHitsThetaTemp.size() > 1) {
909  float dtheta = fabs((float)muonRecHitsThetaTemp.back()->globalPosition().theta() - (float)muonRecHitsThetaTemp.front()->globalPosition().theta());
910  if (dtheta > dthetamax) {
911  dthetamax = dtheta;
912  muonRecHitsThetaBest = muonRecHitsThetaTemp;
913  }
914  } //at least two hits
915  }//loop over seeds
916  }//not empty container2
917 
918  //fill deltaRs
919  if (muonRecHitsThetaBest.size() > 1 && muonRecHitsPhiBest.size() > 1)
920  theStationShowerDeltaR.at(stat) = sqrt(pow(deltaPhi(muonRecHitsPhiBest.front()->globalPosition().barePhi(),muonRecHitsPhiBest.back()->globalPosition().barePhi()),2)+pow(muonRecHitsThetaBest.front()->globalPosition().theta()-muonRecHitsThetaBest.back()->globalPosition().theta(),2));
921 
922  }//loop over station
923 
924  LogTrace(category_) << "deltaR around a track containing all the station hits, by station "
925  << theStationShowerDeltaR.at(0) << " "
926  << theStationShowerDeltaR.at(1) << " "
927  << theStationShowerDeltaR.at(2) << " "
928  << theStationShowerDeltaR.at(3) << endl;
929 
930 
931  LogTrace(category_) << "Transverse cluster size, by station "
932  << theStationShowerTSize.at(0) << " "
933  << theStationShowerTSize.at(1) << " "
934  << theStationShowerTSize.at(2) << " "
935  << theStationShowerTSize.at(3) << endl;
936 
937  return;
938 
939 }
940 
MuonTransientTrackingRecHit::MuonRecHitContainer MuonRecHitContainer
double p() const
momentum vector magnitude
Definition: TrackBase.h:615
EDGetTokenT< ProductType > consumes(edm::InputTag const &tag)
virtual void setEvent(const edm::Event &)
pass the Event to the algorithm at each event
T getParameter(std::string const &) const
std::pair< const_iterator, const_iterator > range
iterator range
Definition: RangeMap.h:50
bool isStandAloneMuon() const override
Definition: Muon.h:278
T perp() const
Definition: PV3DBase.h:72
edm::ESHandle< MagneticField > theField
def copy(args, dbName)
reco::MuonShower fillShowerInformation(const reco::Muon &muon, const edm::Event &, const edm::EventSetup &)
fill muon shower variables
TrajectoryStateOnSurface outerStateOnSurface(const reco::Track &tk, const TrackingGeometry &geom, const MagneticField *field, bool withErr=true)
void setServices(const edm::EventSetup &)
set the services needed
T mag() const
The vector magnitude. Equivalent to sqrt(vec.mag2())
static const double slope[3]
Global3DPoint GlobalPoint
Definition: GlobalPoint.h:10
constexpr uint32_t rawId() const
get the raw id
Definition: DetId.h:47
Geom::Theta< T > theta() const
T y() const
Definition: PV3DBase.h:63
def setup(process, global_tag, zero_tesla=False)
Definition: GeneralSetup.py:1
GlobalPoint globalPosition() const
double phi() const
azimuthal angle of momentum vector
Definition: TrackBase.h:645
edm::EDGetTokenT< CSCSegmentCollection > theCSCSegmentsToken
virtual const BoundCylinder & specificSurface() const final
Extension of the interface.
edm::ESHandle< GeometricSearchTracker > theTracker
edm::ESHandle< CSCGeometry > theCSCGeometry
edm::ESHandle< DTGeometry > theDTGeometry
std::vector< int > nStationHits
number of all the muon RecHits per chamber crossed by a track (1D hits)
Definition: MuonShower.h:10
#define nullptr
edm::EDGetTokenT< CSCRecHit2DCollection > theCSCRecHitToken
virtual ~MuonShowerInformationFiller()
destructor
static TransientTrackingRecHit::ConstRecHitContainer breakInSubRecHits(TransientTrackingRecHit::ConstRecHitPointer, int granularity)
takes a muon rechit and returns its sub-rechits given a certain granularity
T barePhi() const
Definition: PV3DBase.h:68
std::vector< const GeomDet * > dtPositionToDets(const GlobalPoint &) const
std::vector< int > nStationCorrelatedHits
number of the muon RecHits used by segments per chamber crossed by a track
Definition: MuonShower.h:12
int iEvent
Definition: GenABIO.cc:230
T mag() const
Definition: PV3DBase.h:67
double eta() const
pseudorapidity of momentum vector
Definition: TrackBase.h:651
void fillHitsByStation(const reco::Muon &)
Scalar radius() const
Radius of the cylinder.
Definition: Cylinder.h:67
int n0
Definition: AMPTWrapper.h:34
static const int maxLayerId
highest layer id
Definition: DTChamberId.h:85
bool isGlobalMuon() const override
Definition: Muon.h:276
std::shared_ptr< TrackingRecHit const > ConstRecHitPointer
T sqrt(T t)
Definition: SSEVec.h:18
T z() const
Definition: PV3DBase.h:64
edm::Handle< DTRecHitCollection > theDTRecHits
constexpr int subdetId() const
get the contents of the subdetector field (not cast into any detector&#39;s numbering enum) ...
Definition: DetId.h:41
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
static const int minLayerId
lowest layer id. 0 indicates a full SL
Definition: DTChamberId.h:83
DetId geographicalId() const
The label of this GeomDet.
Definition: GeomDet.h:79
GlobalPoint crossingPoint(const GlobalPoint &, const GlobalPoint &, const BarrelDetLayer *) const
#define end
Definition: vmac.h:39
T min(T a, T b)
Definition: MathUtil.h:58
static const int maxSuperLayerId
highest superlayer id
Definition: DTChamberId.h:81
double p2[4]
Definition: TauolaWrapper.h:90
#define LogTrace(id)
edm::Handle< CSCSegmentCollection > theCSCSegments
virtual TrackRef outerTrack() const
reference to Track reconstructed in the muon detector only
Definition: Muon.h:51
TransientTrackingRecHit::ConstRecHitContainer findThetaCluster(TransientTrackingRecHit::ConstRecHitContainer &, const GlobalPoint &) const
edm::ESHandle< TransientTrackingRecHitBuilder > theTrackerRecHitBuilder
#define M_PI
std::vector< ConstRecHitPointer > ConstRecHitContainer
Definition: DetId.h:18
virtual const BoundDisk & specificSurface() const final
TransientTrackingRecHit::ConstRecHitContainer hitsFromSegments(const GeomDet *, edm::Handle< DTRecSegment4DCollection >, edm::Handle< CSCSegmentCollection >) const
edm::EDGetTokenT< DTRecSegment4DCollection > theDT4DRecSegmentToken
int iseed
Definition: AMPTWrapper.h:124
std::vector< const GeomDet * > getCompatibleDets(const reco::Track &) const
edm::Handle< CSCRecHit2DCollection > theCSCRecHits
static constexpr int RPC
Definition: MuonSubdetId.h:14
static const int minSuperLayerId
loweset super layer id. 0 indicates a full chamber
Definition: DTChamberId.h:79
edm::ESHandle< TransientTrackingRecHitBuilder > theMuonRecHitBuilder
std::vector< const GeomDet * > cscPositionToDets(const GlobalPoint &) const
T perp() const
Magnitude of transverse component.
#define begin
Definition: vmac.h:32
HLT enums.
double p1[4]
Definition: TauolaWrapper.h:89
double a
Definition: hdecay.h:121
T get() const
Definition: EventSetup.h:63
std::vector< float > stationShowerSizeT
the transverse size of the hit cluster
Definition: MuonShower.h:14
step
edm::EDGetTokenT< DTRecHitCollection > theDTRecHitToken
static constexpr int DT
Definition: MuonSubdetId.h:12
edm::ESHandle< GlobalTrackingGeometry > theTrackingGeometry
static constexpr int CSC
Definition: MuonSubdetId.h:13
T x() const
Definition: PV3DBase.h:62
MuonRecHitContainer findPerpCluster(MuonRecHitContainer &muonRecHits) const
static MuonRecHitPointer specificBuild(const GeomDet *geom, const TrackingRecHit *rh)
std::vector< MuonRecHitPointer > MuonRecHitContainer
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:40
edm::Handle< DTRecSegment4DCollection > theDT4DRecSegments
Definition: event.py:1
TrajectoryStateOnSurface innerStateOnSurface(const reco::Track &tk, const TrackingGeometry &geom, const MagneticField *field, bool withErr=true)
virtual TrackRef globalTrack() const
reference to Track reconstructed in both tracked and muon detector
Definition: Muon.h:54
std::vector< float > stationShowerDeltaR
the radius of the cone containing the all the hits around the track
Definition: MuonShower.h:16
constexpr Detector det() const
get the detector field from this detid
Definition: DetId.h:39