CMS 3D CMS Logo

GeometryTranslator.cc
Go to the documentation of this file.
2 
5 
14 
18 
20 
21 #include <cmath> // for pi
22 
23 using namespace L1TMuon;
24 
26  : _geom_cache_id(0ULL),
27  geodtToken_(iC.esConsumes()),
28  geocscToken_(iC.esConsumes()),
29  georpcToken_(iC.esConsumes()),
30  geogemToken_(iC.esConsumes()),
31  geome0Token_(iC.esConsumes()),
32  _magfield_cache_id(0ULL),
33  magfieldToken_(iC.esConsumes()) {}
34 
36 
38  switch (tp.subsystem()) {
39  case L1TMuon::kDT:
40  return calcDTSpecificEta(tp);
41  break;
42  case L1TMuon::kCSC:
43  return calcCSCSpecificEta(tp);
44  break;
45  case L1TMuon::kRPC:
46  return calcRPCSpecificEta(tp);
47  break;
48  case L1TMuon::kGEM:
49  return calcGEMSpecificEta(tp);
50  break;
51  case L1TMuon::kME0:
52  return calcME0SpecificEta(tp);
53  break;
54  default:
55  return std::nan("Invalid TP type!");
56  break;
57  }
58 }
59 
61  switch (tp.subsystem()) {
62  case L1TMuon::kDT:
63  return calcDTSpecificPhi(tp);
64  break;
65  case L1TMuon::kCSC:
66  return calcCSCSpecificPhi(tp);
67  break;
68  case L1TMuon::kRPC:
69  return calcRPCSpecificPhi(tp);
70  break;
71  case L1TMuon::kGEM:
72  return calcGEMSpecificPhi(tp);
73  break;
74  case L1TMuon::kME0:
75  return calcME0SpecificPhi(tp);
76  break;
77  default:
78  return std::nan("Invalid TP type!");
79  break;
80  }
81 }
82 
84  switch (tp.subsystem()) {
85  case L1TMuon::kDT:
86  return calcDTSpecificBend(tp);
87  break;
88  case L1TMuon::kCSC:
89  return calcCSCSpecificBend(tp);
90  break;
91  case L1TMuon::kRPC:
92  return calcRPCSpecificBend(tp);
93  break;
94  case L1TMuon::kGEM:
95  return calcGEMSpecificBend(tp);
96  break;
97  case L1TMuon::kME0:
98  return calcME0SpecificBend(tp);
99  break;
100  default:
101  return std::nan("Invalid TP type!");
102  break;
103  }
104 }
105 
107  switch (tp.subsystem()) {
108  case L1TMuon::kDT:
109  return calcDTSpecificPoint(tp);
110  break;
111  case L1TMuon::kCSC:
112  return getCSCSpecificPoint(tp);
113  break;
114  case L1TMuon::kRPC:
115  return getRPCSpecificPoint(tp);
116  break;
117  case L1TMuon::kGEM:
118  return getGEMSpecificPoint(tp);
119  break;
120  case L1TMuon::kME0:
121  return getME0SpecificPoint(tp);
122  break;
123  default:
125  GlobalPoint::Polar(std::nan("Invalid TP type!"), std::nan("Invalid TP type!"), std::nan("Invalid TP type!")));
126  return ret;
127  break;
128  }
129 }
130 
133  unsigned long long geomid = geom.cacheIdentifier();
134  if (_geom_cache_id != geomid) {
135  _geodt = geom.getHandle(geodtToken_);
136  _geocsc = geom.getHandle(geocscToken_);
137  _georpc = geom.getHandle(georpcToken_);
138  _geogem = geom.getHandle(geogemToken_);
139  _geome0 = geom.getHandle(geome0Token_);
140  _geom_cache_id = geomid;
141  }
142 
144  unsigned long long magfieldid = magfield.cacheIdentifier();
145  if (_magfield_cache_id != magfieldid) {
146  _magfield = magfield.getHandle(magfieldToken_);
147  _magfield_cache_id = magfieldid;
148  }
149 }
150 
151 // _____________________________________________________________________________
152 // ME0
154  const ME0DetId id(tp.detId<ME0DetId>());
155  const ME0Chamber* chamber = _geome0->chamber(id);
156  const ME0Layer* keylayer = chamber->layer(3); // ME0 key layer is layer 3
157  int partition = tp.getME0Data().partition; // 'partition' is in half-roll unit
158  int iroll = (partition >> 1) + 1;
159  const ME0EtaPartition* roll = keylayer->etaPartition(iroll);
160  assert(roll != nullptr); // failed to get ME0 roll
161  // See L1Trigger/ME0Trigger/src/ME0TriggerPseudoBuilder.cc
162  int phiposition = tp.getME0Data().phiposition; // 'phiposition' is in half-strip unit
163  int istrip = (phiposition >> 1);
164  int phiposition2 = (phiposition & 0x1);
165  float centreOfStrip = istrip + 0.25 + phiposition2 * 0.5;
166  const LocalPoint& lp = roll->centreOfStrip(centreOfStrip);
167  const GlobalPoint& gp = roll->surface().toGlobal(lp);
168  return gp;
169 }
170 
172  return getME0SpecificPoint(tp).eta();
173 }
174 
176  return getME0SpecificPoint(tp).phi();
177 }
178 
180  return tp.getME0Data().deltaphi * (tp.getME0Data().bend == 0 ? 1 : -1);
181 }
182 
183 // _____________________________________________________________________________
184 // GEM
186  const GEMDetId id(tp.detId<GEMDetId>());
188  assert(roll != nullptr); // failed to get GEM roll
189  //const uint16_t pad = tp.getGEMData().pad;
190  // Use half-pad precision, + 0.5 at the end to get the center of the pad (pad starts from 0)
191  const float pad = (0.5 * static_cast<float>(tp.getGEMData().pad_low + tp.getGEMData().pad_hi)) + 0.5f;
192  const LocalPoint& lp = roll->centreOfPad(pad);
193  const GlobalPoint& gp = roll->surface().toGlobal(lp);
194  return gp;
195 }
196 
198  return getGEMSpecificPoint(tp).eta();
199 }
200 
202  return getGEMSpecificPoint(tp).phi();
203 }
204 
205 double GeometryTranslator::calcGEMSpecificBend(const TriggerPrimitive& tp) const { return 0.0; }
206 
207 // _____________________________________________________________________________
208 // RPC
210  const RPCDetId id(tp.detId<RPCDetId>());
211  const RPCRoll* roll = _georpc->roll(id);
212  assert(roll != nullptr); // failed to get RPC roll
213  //const int strip = static_cast<int>(tp.getRPCData().strip);
214  // Use half-strip precision, - 0.5 at the end to get the center of the strip (strip starts from 1)
215  const float strip = (0.5 * static_cast<float>(tp.getRPCData().strip_low + tp.getRPCData().strip_hi)) - 0.5f;
216  const LocalPoint& lp = roll->centreOfStrip(strip);
217  const GlobalPoint& gp = roll->surface().toGlobal(lp);
218  return gp;
219 }
220 
222  return getRPCSpecificPoint(tp).eta();
223 }
224 
226  return getRPCSpecificPoint(tp).phi();
227 }
228 
229 // this function actually does nothing since RPC
230 // hits are point-like objects
231 double GeometryTranslator::calcRPCSpecificBend(const TriggerPrimitive& tp) const { return 0.0; }
232 
233 // _____________________________________________________________________________
234 // CSC
235 //
236 // alot of this is transcription and consolidation of the CSC
237 // global phi calculation code
238 // this works directly with the geometry
239 // rather than using the old phi luts
241  const CSCDetId id(tp.detId<CSCDetId>());
242  // we should change this to weak_ptrs at some point
243  // requires introducing std::shared_ptrs to geometry
244  std::unique_ptr<const CSCChamber> chamb(_geocsc->chamber(id));
245  assert(chamb != nullptr); // failed to get CSC chamber
246  std::unique_ptr<const CSCLayerGeometry> layer_geom(chamb->layer(CSCConstants::KEY_ALCT_LAYER)->geometry());
247  std::unique_ptr<const CSCLayer> layer(chamb->layer(CSCConstants::KEY_ALCT_LAYER));
248 
249  const uint16_t halfstrip = tp.getCSCData().strip;
250  const uint16_t pattern = tp.getCSCData().pattern;
251  const uint16_t keyWG = tp.getCSCData().keywire;
252  //const unsigned maxStrips = layer_geom->numberOfStrips();
253 
254  // so we can extend this later
255  // assume TMB2007 half-strips only as baseline
256  double offset = 0.0;
257  switch (1) {
258  case 1:
260  }
261  const unsigned halfstrip_offs = static_cast<unsigned>(0.5 + halfstrip + offset);
262  const unsigned strip = halfstrip_offs / 2 + 1; // geom starts from 1
263 
264  // the rough location of the hit at the ALCT key layer
265  // we will refine this using the half strip information
266  const LocalPoint& coarse_lp = layer_geom->stripWireGroupIntersection(strip, keyWG);
267  const GlobalPoint& coarse_gp = layer->surface().toGlobal(coarse_lp);
268 
269  // the strip width/4.0 gives the offset of the half-strip
270  // center with respect to the strip center
271  const double hs_offset = layer_geom->stripPhiPitch() / 4.0;
272 
273  // determine handedness of the chamber
274  const bool ccw = isCSCCounterClockwise(layer);
275  // we need to subtract the offset of even half strips and add the odd ones
276  const double phi_offset = ((halfstrip_offs % 2 ? 1 : -1) * (ccw ? -hs_offset : hs_offset));
277 
278  // the global eta calculation uses the middle of the strip
279  // so no need to increment it
280  const GlobalPoint final_gp(
281  GlobalPoint::Polar(coarse_gp.theta(), (coarse_gp.phi().value() + phi_offset), coarse_gp.mag()));
282 
283  // We need to add in some notion of the 'error' on trigger primitives
284  // like the width of the wire group by the width of the strip
285  // or something similar
286 
287  // release ownership of the pointers
288  chamb.release();
289  layer_geom.release();
290  layer.release();
291 
292  return final_gp;
293 }
294 
296  return getCSCSpecificPoint(tp).eta();
297 }
298 
300  return getCSCSpecificPoint(tp).phi();
301 }
302 
303 double GeometryTranslator::calcCSCSpecificBend(const TriggerPrimitive& tp) const { return tp.getCSCData().bend; }
304 
305 bool GeometryTranslator::isCSCCounterClockwise(const std::unique_ptr<const CSCLayer>& layer) const {
306  const int nStrips = layer->geometry()->numberOfStrips();
307  const double phi1 = layer->centerOfStrip(1).phi();
308  const double phiN = layer->centerOfStrip(nStrips).phi();
309  return ((std::abs(phi1 - phiN) < M_PI && phi1 >= phiN) || (std::abs(phi1 - phiN) >= M_PI && phi1 < phiN));
310 }
311 
312 // _____________________________________________________________________________
313 // DT
315  const DTChamberId baseid(tp.detId<DTChamberId>());
316  // do not use this pointer for anything other than creating a trig geom
317  std::unique_ptr<DTChamber> chamb(const_cast<DTChamber*>(_geodt->chamber(baseid)));
318  std::unique_ptr<DTTrigGeom> trig_geom(new DTTrigGeom(chamb.get(), false));
319  chamb.release(); // release it here so no one gets funny ideas
320  // super layer one is the theta superlayer in a DT chamber
321  // station 4 does not have a theta super layer
322  // the BTI index from the theta trigger is an OR of some BTI outputs
323  // so, we choose the BTI that's in the middle of the group
324  // as the BTI that we get theta from
325  // TODO:::::>>> need to make sure this ordering doesn't flip under wheel sign
326  const int NBTI_theta = ((baseid.station() != 4) ? trig_geom->nCell(2) : trig_geom->nCell(3));
327  const int bti_group = tp.getDTData().theta_bti_group;
328  const unsigned bti_actual = bti_group * NBTI_theta / 7 + NBTI_theta / 14 + 1;
329  DTBtiId thetaBTI;
330  if (baseid.station() != 4 && bti_group != -1) {
331  thetaBTI = DTBtiId(baseid, 2, bti_actual);
332  } else {
333  // since this is phi oriented it'll give us theta in the middle
334  // of the chamber
335  thetaBTI = DTBtiId(baseid, 3, 1);
336  }
337  const GlobalPoint& theta_gp = trig_geom->CMSPosition(thetaBTI);
338 
339  // local phi in sector -> global phi
340  double phi = static_cast<double>(tp.getDTData().radialAngle) / 4096.0; // 12 bits for 1 radian
341  phi += tp.getDTData().sector * M_PI / 6.0; // add sector offset, sector is [0,11]
342 
343  return GlobalPoint(GlobalPoint::Polar(theta_gp.theta(), phi, theta_gp.mag()));
344 }
345 
347 
349 
350 // we have the bend except for station 3
352  int bend = tp.getDTData().bendingAngle;
353  double bendf = bend / 512.0;
354  return bendf;
355 }
int station() const
Return the station number.
Definition: DTChamberId.h:42
edm::ESHandle< DTGeometry > _geodt
ESGetTokenH3DDVariant esConsumes(std::string const &Record, edm::ConsumesCollector &)
Definition: DeDxTools.cc:283
const GEMEtaPartition * etaPartition(GEMDetId id) const
Return a GEMEtaPartition given its id.
Definition: GEMGeometry.cc:77
GlobalPoint getCSCSpecificPoint(const TriggerPrimitive &) const
const CSCChamber * chamber(CSCDetId id) const
Return the chamber corresponding to given DetId.
Definition: CSCGeometry.cc:100
unsigned long long _geom_cache_id
double calcGEMSpecificPhi(const TriggerPrimitive &) const
GlobalPoint getGlobalPoint(const TriggerPrimitive &) const
ret
prodAgent to be discontinued
Geom::Phi< T > phi() const
Definition: PV3DBase.h:66
double calcCSCSpecificPhi(const TriggerPrimitive &) const
T eta() const
Definition: PV3DBase.h:73
edm::ESHandle< RPCGeometry > _georpc
edm::ESHandle< GEMGeometry > _geogem
edm::ESHandle< ME0Geometry > _geome0
Global3DPoint GlobalPoint
Definition: GlobalPoint.h:10
double calcRPCSpecificPhi(const TriggerPrimitive &) const
double calculateGlobalPhi(const TriggerPrimitive &) const
const RPCRoll * roll(RPCDetId id) const
Return a roll given its id.
Definition: RPCGeometry.cc:50
assert(be >=bs)
double calcGEMSpecificEta(const TriggerPrimitive &) const
nStrips
1.2 is to make the matching window safely the two nearest strips 0.35 is the size of an ME0 chamber i...
edm::ESHandle< MagneticField > _magfield
edm::ESGetToken< DTGeometry, MuonGeometryRecord > geodtToken_
double calcRPCSpecificEta(const TriggerPrimitive &) const
GeometryTranslator(edm::ConsumesCollector)
void checkAndUpdateGeometry(const edm::EventSetup &)
edm::ESHandle< CSCGeometry > _geocsc
double calcDTSpecificBend(const TriggerPrimitive &) const
const ME0Chamber * chamber(ME0DetId id) const
Return a chamber given its id.
Definition: ME0Geometry.cc:43
T mag() const
Definition: PV3DBase.h:64
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
T get() const
Definition: EventSetup.h:79
double calcME0SpecificBend(const TriggerPrimitive &) const
GlobalPoint getRPCSpecificPoint(const TriggerPrimitive &) const
double calcGEMSpecificBend(const TriggerPrimitive &) const
double calcCSCSpecificEta(const TriggerPrimitive &) const
edm::ESGetToken< ME0Geometry, MuonGeometryRecord > geome0Token_
#define M_PI
double calcME0SpecificEta(const TriggerPrimitive &) const
double calcCSCSpecificBend(const TriggerPrimitive &) const
double calculateGlobalEta(const TriggerPrimitive &) const
double calcDTSpecificPhi(const TriggerPrimitive &) const
edm::ESGetToken< MagneticField, IdealMagneticFieldRecord > magfieldToken_
double calcRPCSpecificBend(const TriggerPrimitive &) const
static double getLegacyPosition(int pattern)
double calcDTSpecificEta(const TriggerPrimitive &) const
edm::ESGetToken< RPCGeometry, MuonGeometryRecord > georpcToken_
edm::ESGetToken< CSCGeometry, MuonGeometryRecord > geocscToken_
T1 value() const
Explicit access to value in case implicit conversion not OK.
Definition: Phi.h:75
bool isCSCCounterClockwise(const std::unique_ptr< const CSCLayer > &) const
edm::ESGetToken< GEMGeometry, MuonGeometryRecord > geogemToken_
unsigned long long _magfield_cache_id
GlobalPoint getGEMSpecificPoint(const TriggerPrimitive &) const
const DTChamber * chamber(const DTChamberId &id) const
Return a DTChamber given its id.
Definition: DTGeometry.cc:90
double calcME0SpecificPhi(const TriggerPrimitive &) const
double calculateBendAngle(const TriggerPrimitive &) const
Geom::Theta< T > theta() const
Definition: PV3DBase.h:72
GlobalPoint getME0SpecificPoint(const TriggerPrimitive &) const
GlobalPoint calcDTSpecificPoint(const TriggerPrimitive &) const
const ME0EtaPartition * etaPartition(ME0DetId id) const
Return the eta partition corresponding to the given id.
Definition: ME0Layer.cc:27