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