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