CMS 3D CMS Logo

OmtfAngleConverter.cc
Go to the documentation of this file.
1 /*
2  * OmtfAngleConverter.cpp
3  *
4  * Created on: Jan 14, 2019
5  * Author: kbunkow
6  */
7 
10 
13 
16 
20 
25 
27 
28 #include <cmath>
29 
30 namespace {
31  template <typename T>
32  int sgn(T val) {
33  return (T(0) < val) - (val < T(0));
34  }
35 
36  //DT eta bins in the wheel +2
37  const std::vector<float> bounds = {1.24, 1.14353, 1.09844, 1.05168, 1.00313, 0.952728, 0.90037, 0.8};
38  // 0.8 -> 73
39  // 0.85 -> 78
40  // 0.9265 -> 85
41  // 0.9779 -> 89.9 -> 90
42  // 1.0274 -> 94.4 -> 94
43  // 1.07506 -> 98.9 -> 99
44  // 1.121 -> 103
45  // 1.2 -> 110
46  // 1.25 -> 115
47  //
48  // other (1.033) -> 1.033 -> 95
49 
50  int etaVal2Bit(float eta) { return bounds.rend() - std::lower_bound(bounds.rbegin(), bounds.rend(), fabs(eta)); }
51 
52  int etaVal2Code(double etaVal) {
53  int sign = sgn(etaVal);
54  int bit = etaVal2Bit(fabs(etaVal));
56  return sign * code;
57  }
58 
59  int etaKeyWG2Code(const CSCDetId &detId, uint16_t keyWG) {
60  signed int etaCode = 121;
61  if (detId.station() == 1 && detId.ring() == 2) {
62  if (keyWG < 49)
63  etaCode = 121;
64  else if (keyWG <= 57)
65  etaCode = OMTFConfiguration::etaBit2Code(0);
66  else if (keyWG <= 63)
67  etaCode = OMTFConfiguration::etaBit2Code(1);
68  } else if (detId.station() == 1 && detId.ring() == 3) {
69  if (keyWG <= 2)
70  etaCode = OMTFConfiguration::etaBit2Code(2);
71  else if (keyWG <= 8)
72  etaCode = OMTFConfiguration::etaBit2Code(3);
73  else if (keyWG <= 15)
74  etaCode = OMTFConfiguration::etaBit2Code(4);
75  else if (keyWG <= 23)
76  etaCode = OMTFConfiguration::etaBit2Code(5);
77  else if (keyWG <= 31)
78  etaCode = OMTFConfiguration::etaBit2Code(6);
79  } else if ((detId.station() == 2 || detId.station() == 3) && detId.ring() == 2) {
80  if (keyWG < 24)
81  etaCode = 121;
82  else if (keyWG <= 29)
83  etaCode = OMTFConfiguration::etaBit2Code(0);
84  else if (keyWG <= 43)
85  etaCode = OMTFConfiguration::etaBit2Code(1);
86  else if (keyWG <= 49)
87  etaCode = OMTFConfiguration::etaBit2Code(2);
88  else if (keyWG <= 56)
89  etaCode = OMTFConfiguration::etaBit2Code(3);
90  else if (keyWG <= 63)
91  etaCode = OMTFConfiguration::etaBit2Code(4);
92  }
93 
94  if (detId.endcap() == 2)
95  etaCode *= -1;
96  return etaCode;
97  }
98 
99 } //namespace
100 
102 
106  const L1MuDTChambThContainer *dtThDigis,
107  int bxNum) const {
108  //const DTChamberId dTChamberId(aDigi.whNum(),aDigi.stNum(),aDigi.scNum()+1);
109  DTTrigGeom trig_geom(_geodt->chamber(dTChamberId), false);
110 
111  // super layer one is the theta superlayer in a DT chamber
112  // station 4 does not have a theta super layer
113  // the BTI index from the theta trigger is an OR of some BTI outputs
114  // so, we choose the BTI that's in the middle of the group
115  // as the BTI that we get theta from
116  // TODO:::::>>> need to make sure this ordering doesn't flip under wheel sign
117  const int NBTI_theta = ((dTChamberId.station() != 4) ? trig_geom.nCell(2) : trig_geom.nCell(3));
118 
119  const L1MuDTChambThDigi *theta_segm =
120  dtThDigis->chThetaSegm(dTChamberId.wheel(), dTChamberId.station(), dTChamberId.sector() - 1, bxNum);
121 
122  int bti_group = -1;
123  if (theta_segm) {
124  for (unsigned int i = 0; i < 7; ++i)
125  if (theta_segm->position(i) && bti_group < 0)
126  bti_group = i;
127  else if (theta_segm->position(i) && bti_group > -1)
128  bti_group = 511;
129  }
130 
131  //TODO why bti_group == 511 (meaning there is more then one bit fired) is converted into 95, but not into middle of the chamber?
132  int iEta = 0;
133  if (bti_group == 511)
134  iEta = 95;
135  else if (bti_group == -1 && dTChamberId.station() == 1)
136  iEta = 92;
137  else if (bti_group == -1 && dTChamberId.station() == 2)
138  iEta = 79;
139  else if (bti_group == -1 && dTChamberId.station() == 3)
140  iEta = 75;
141  else if (dTChamberId.station() != 4 && bti_group >= 0) {
142  unsigned bti_actual = bti_group * NBTI_theta / 7 + NBTI_theta / 14 + 1;
143  DTBtiId thetaBTI = DTBtiId(dTChamberId, 2, bti_actual);
144  GlobalPoint theta_gp = trig_geom.CMSPosition(thetaBTI);
145  iEta = etaVal2Code(fabs(theta_gp.eta()));
146  }
147  int signEta = sgn(dTChamberId.wheel());
148  iEta *= signEta;
149 
150  if (config->getStubEtaEncoding() == ProcConfigurationBase::StubEtaEncoding::bits)
152  else if (config->getStubEtaEncoding() == ProcConfigurationBase::StubEtaEncoding::valueP1Scale)
153  return abs(iEta);
154 
155  return 0;
156 }
157 
160 int OmtfAngleConverter::getGlobalEta(unsigned int rawid, const CSCCorrelatedLCTDigi &aDigi, float &r) const {
164 
165  // a lot of this is transcription and consolidation of the CSC
166  // global phi calculation code
167  // this works directly with the geometry
168  // rather than using the old phi luts
169  const CSCDetId id(rawid);
170  // we should change this to weak_ptrs at some point
171  // requires introducing std::shared_ptrs to geometry
172  auto chamb = _geocsc->chamber(id);
173  auto layer_geom = chamb->layer(CSCConstants::KEY_ALCT_LAYER)->geometry();
174  auto layer = chamb->layer(CSCConstants::KEY_ALCT_LAYER);
175 
176  const uint16_t halfstrip = aDigi.getStrip();
177  //const uint16_t pattern = aDigi.getPattern();
178  const uint16_t keyWG = aDigi.getKeyWG();
179  //const unsigned maxStrips = layer_geom->numberOfStrips();
180 
181  // so we can extend this later
182  // assume TMB2007 half-strips only as baseline
183  double offset = 0.0;
184  //K.B. CSCPatternLUT is removed since CMSSW_11_2_1, but it looks that this offset is effectively not needed here
185  //offset = CSCPatternLUT::get2007Position(pattern);
186 
187  const unsigned halfstrip_offs = unsigned(0.5 + halfstrip + offset);
188  const unsigned strip = halfstrip_offs / 2 + 1; // geom starts from 1
189 
190  // the rough location of the hit at the ALCT key layer
191  // we will refine this using the half strip information
192  const LocalPoint coarse_lp = layer_geom->stripWireGroupIntersection(strip, keyWG);
193  const GlobalPoint coarse_gp = layer->surface().toGlobal(coarse_lp);
194 
195  // the strip width/4.0 gives the offset of the half-strip
196  // center with respect to the strip center
197  const double hs_offset = layer_geom->stripPhiPitch() / 4.0;
198 
199  // determine handedness of the chamber
200  const bool ccw = isCSCCounterClockwise(layer);
201  // we need to subtract the offset of even half strips and add the odd ones
202  const double phi_offset = ((halfstrip_offs % 2 ? 1 : -1) * (ccw ? -hs_offset : hs_offset));
203 
204  // the global eta calculation uses the middle of the strip
205  // so no need to increment it
206  const GlobalPoint final_gp(
207  GlobalPoint::Polar(coarse_gp.theta(), (coarse_gp.phi().value() + phi_offset), coarse_gp.mag()));
208 
209  //TODO for phase 2, add firmware like, fixed point conversion from keyWG to eta and r
210  const LocalPoint lpWg = layer_geom->localCenterOfWireGroup(keyWG);
211  const GlobalPoint gpWg = layer->surface().toGlobal(lpWg);
212  r = round(gpWg.perp());
213 
214  if (config->getStubEtaEncoding() == ProcConfigurationBase::StubEtaEncoding::bits)
215  return OMTFConfiguration::eta2Bits(abs(etaKeyWG2Code(id, keyWG)));
216  else if (config->getStubEtaEncoding() == ProcConfigurationBase::StubEtaEncoding::valueP1Scale) {
217  return config->etaToHwEta(abs(gpWg.eta()));
218  } else {
219  return 0;
220  }
221 }
224 int OmtfAngleConverter::getGlobalEtaRpc(unsigned int rawid, const unsigned int &strip, float &r) const {
225  const RPCDetId id(rawid);
226  auto roll = _georpc->roll(id);
227  const LocalPoint lp = roll->centreOfStrip((int)strip);
228  const GlobalPoint gp = roll->toGlobal(lp);
229 
230  if (id.region() != 0) { //outside barrel
231  r = gp.perp();
232  }
233 
234  if (config->getStubEtaEncoding() == ProcConfigurationBase::StubEtaEncoding::bits)
235  return OMTFConfiguration::eta2Bits(abs(etaVal2Code(gp.eta())));
236  else if (config->getStubEtaEncoding() == ProcConfigurationBase::StubEtaEncoding::valueP1Scale)
237  return abs(config->etaToHwEta((gp.eta())));
238 
239  return 0;
240 }
241 
int station() const
Return the station number.
Definition: DTChamberId.h:45
edm::ESHandle< DTGeometry > _geodt
const CSCLayer * layer(CSCDetId id) const
Return the layer corresponding to the given id.
Definition: CSCChamber.cc:30
L1MuDTChambThDigi const * chThetaSegm(int wheel, int stat, int sect, int bx) const
T perp() const
Definition: PV3DBase.h:69
const CSCChamber * chamber(CSCDetId id) const
Return the chamber corresponding to given DetId.
Definition: CSCGeometry.cc:100
float sgn(float val)
Definition: FWPFMaths.cc:7
Geom::Phi< T > phi() const
Definition: PV3DBase.h:66
virtual int getGlobalEta(const DTChamberId dTChamberId, const L1MuDTChambThContainer *dtThDigis, int bxNum) const
edm::ESHandle< RPCGeometry > _georpc
T eta() const
Definition: PV3DBase.h:73
int position(const int i) const
Definition: config.py:1
const RPCRoll * roll(RPCDetId id) const
Return a roll given its id.
Definition: RPCGeometry.cc:50
const CSCLayerGeometry * geometry() const
Definition: CSCLayer.h:44
T mag() const
Definition: PV3DBase.h:64
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
static int etaBit2Code(unsigned int bit)
uint16_t getStrip(uint16_t n=2) const
return the key halfstrip from 0,159
static unsigned int eta2Bits(unsigned int eta)
edm::ESHandle< CSCGeometry > _geocsc
virtual int getGlobalEtaRpc(unsigned int rawid, const unsigned int &aDigi, float &r) const
Convert local eta coordinate to global digital microGMT scale.
uint16_t getKeyWG() const
return the key wire group. counts from 0.
int wheel() const
Return the wheel number.
Definition: DTChamberId.h:42
int sector() const
Definition: DTChamberId.h:52
virtual bool isCSCCounterClockwise(const CSCLayer *layer) const
Check orientation of strips in given CSC chamber.
T1 value() const
Explicit access to value in case implicit conversion not OK.
Definition: Phi.h:75
long double T
const DTChamber * chamber(const DTChamberId &id) const
Return a DTChamber given its id.
Definition: DTGeometry.cc:90
Geom::Theta< T > theta() const
Definition: PV3DBase.h:72