CMS 3D CMS Logo

AngleConverter.cc
Go to the documentation of this file.
3 
6 
10 
14 
19 
20 #include <cmath>
21 
22 namespace {
23 template <typename T> int sgn(T val) { return (T(0) < val) - (val < T(0)); }
24 
25 std::vector<float> bounds = { 1.24, 1.14353, 1.09844, 1.05168, 1.00313, 0.952728, 0.90037, 0.8};
26 // 0.8 -> 73
27 // 0.85 -> 78
28 // 0.9265 -> 85
29 // 0.9779 -> 89.9 -> 90
30 // 1.0274 -> 94.4 -> 94
31 // 1.07506 -> 98.9 -> 99
32 // 1.121 -> 103
33 // 1.2 -> 110
34 // 1.25 -> 115
35 //
36 // other (1.033) -> 1.033 -> 95
37 
38 int etaVal2Bit(float eta) { return bounds.rend() - std::lower_bound (bounds.rbegin(), bounds.rend(), fabs(eta) ); }
39 
40 int etaBit2Code( unsigned int bit) {
41  int code = 73;
42  switch (bit) {
43  case 0 : {code = 115; break;}
44  case 1 : {code = 110; break; }
45  case 2 : {code = 103; break; }
46  case 3 : {code = 99; break; }
47  case 4 : {code = 94; break; }
48  case 5 : {code = 90; break; }
49  case 6 : {code = 85; break; }
50  case 7 : {code = 78; break; }
51  case 8 : {code = 73; break; }
52  default: {code = 95; break; }
53  }
54  return code;
55 }
56 
57 int etaVal2Code( double etaVal) {
58  int sign = sgn(etaVal);
59  int bit = etaVal2Bit( fabs(etaVal) );
60  int code = etaBit2Code(bit);
61  return sign*code;
62 }
63 
64 int etaKeyWG2Code(const CSCDetId& detId, uint16_t keyWG) {
65  signed int etaCode = 121;
66  if (detId.station()==1 && detId.ring()==2) {
67  if (keyWG < 49) etaCode = 121;
68  else if (keyWG <=57) etaCode = etaBit2Code(0);
69  else if (keyWG <=63) etaCode = etaBit2Code(1);
70  }
71  else if (detId.station()==1 && detId.ring()==3) {
72  if (keyWG <= 2) etaCode = etaBit2Code(2);
73  else if (keyWG <= 8) etaCode = etaBit2Code(3);
74  else if (keyWG <= 15) etaCode = etaBit2Code(4);
75  else if (keyWG <= 23) etaCode = etaBit2Code(5);
76  else if (keyWG <= 31) etaCode = etaBit2Code(6);
77  }
78  else if ( (detId.station()==2 || detId.station()==3) && detId.ring()==2) {
79  if (keyWG < 24) etaCode = 121;
80  else if (keyWG <= 29) etaCode = etaBit2Code(0);
81  else if (keyWG <= 43) etaCode = etaBit2Code(1);
82  else if (keyWG <= 49) etaCode = etaBit2Code(2);
83  else if (keyWG <= 56) etaCode = etaBit2Code(3);
84  else if (keyWG <= 63) etaCode = etaBit2Code(4);
85  }
86 
87  if (detId.endcap()==2) etaCode *= -1;
88  return etaCode;
89 }
90 
91 }
92 
93 
100 void AngleConverter::checkAndUpdateGeometry(const edm::EventSetup& es, unsigned int phiBins) {
102  unsigned long long geomid = geom.cacheIdentifier();
103  if( _geom_cache_id != geomid ) {
104  geom.get(_georpc);
105  geom.get(_geocsc);
106  geom.get(_geodt);
107  _geom_cache_id = geomid;
108  }
109 
110  nPhiBins = phiBins;
111 
112 }
115 int AngleConverter::getProcessorPhi(unsigned int iProcessor, l1t::tftype part, const L1MuDTChambPhDigi &digi) const
116 {
117 
118  double hsPhiPitch = 2*M_PI/nPhiBins; // width of phi Pitch, related to halfStrip at CSC station 2
119  const int dummy = nPhiBins;
120  int processor= iProcessor+1; // FIXME: get from OMTF name when available
121  int posneg = (part==l1t::tftype::omtf_pos) ? 1 : -1; // FIXME: get from OMTF name
122 
123  int sector = digi.scNum()+1; //NOTE: there is a inconsistency in DT sector numb. Thus +1 needed to get detector numb.
124  int wheel = digi.whNum();
125  int station = digi.stNum();
126  int phiDT = digi.phi();
127 
128  if (posneg*2 != wheel) return dummy;
129  if (station > 3 ) return dummy;
130 
131  //FIXME: update the following two lines with proper method when Connections introduced
132  if (processor !=6 && !(sector >= processor*2-1 && sector <= processor*2+1) ) return dummy;
133  if (processor ==6 && !(sector >= 11 || sector==1) ) return dummy;
134 
135  // ichamber is consecutive chamber connected to processor, starting from 0 (overlaping one)
136  int ichamber = sector-1-2*(processor-1);
137  if (ichamber < 0) ichamber += 12;
138 
139  int offsetLoc = lround( ((ichamber-1)*M_PI/6+M_PI/12.)/hsPhiPitch );
140  double scale = 1./4096/hsPhiPitch;
141  int scale_coeff = lround(scale* pow(2,11));
142 // int phi = static_cast<int>(phiDT*scale) + offsetLoc;
143  int phi = floor(phiDT*scale_coeff/pow(2,11)) + offsetLoc;
144 
145  return phi;
146 }
149 int AngleConverter::getProcessorPhi(unsigned int iProcessor, l1t::tftype part, const CSCDetId & csc, const CSCCorrelatedLCTDigi &digi) const
150 {
151 
152  const double hsPhiPitch = 2*M_PI/nPhiBins;
153  const int dummy = nPhiBins;
154  int processor= iProcessor+1; // FIXME: get from OMTF name when available
155  int posneg = (part==l1t::tftype::omtf_pos) ? 1 : -1; // FIXME: get from OMTF name
156 
157 
158 
159  // filter out chambers not connected to OMTF board
160  // FIXME: temporary - use Connections or relay that filtering done before.
161  if (posneg != csc.zendcap()) return dummy;
162  if ( csc.ring() != 3 && !(csc.ring()==2 && (csc.station()==2 || csc.station()==3 || csc.station()==1)) ) return dummy;
163  if (processor !=6) {
164  if (csc.chamber() < (processor-1)*6 + 2) return dummy;
165  if (csc.chamber() > (processor-1)*6 + 8) return dummy;
166  } else {
167  if (csc.chamber() > 2 && csc.chamber() < 32) return dummy;
168  }
169 
170  //
171  // assign number 0..6, consecutive processor for a processor
172  //
173  //int ichamber = (csc.chamber()-2-6*(processor-1));
174  //if (ichamber < 0) ichamber += 36;
175 
176  //
177  // get offset for each chamber.
178  // FIXME: These parameters depends on processor and chamber only so may be precomputed and put in map
179  //
180  const CSCChamber* chamber = _geocsc->chamber(csc);
181  const CSCChamberSpecs* cspec = chamber->specs();
182  const CSCLayer* layer = chamber->layer(3);
183  int order = ( layer->centerOfStrip(2).phi() - layer->centerOfStrip(1).phi()> 0) ? 1 : -1;
184  double stripPhiPitch = cspec->stripPhiPitch();
185  double scale = fabs(stripPhiPitch/hsPhiPitch/2.); if ( fabs(scale-1.) < 0.0002) scale=1.;
186  double phi15deg = M_PI/3.*(processor-1)+M_PI/12.;
187  double phiHalfStrip0 = layer->centerOfStrip(10).phi() - order*9*stripPhiPitch - order*stripPhiPitch/4.;
188  if ( processor==6 || phiHalfStrip0<0) phiHalfStrip0 += 2*M_PI;
189  int offsetLoc = lround( (phiHalfStrip0-phi15deg)/hsPhiPitch );
190 
191  int halfStrip = digi.getStrip(); // returns halfStrip 0..159
192  //FIXME: to be checked (only important for ME1/3) keep more bits for offset, truncate at the end
193  int phi = offsetLoc + order*scale*halfStrip;
194 
195 // std::cout <<" hs: "<< halfStrip <<" offset: " << offsetLoc <<" oder*scale: "<< order*scale
196 // <<" phi: " <<phi<<" ("<<offsetLoc + order*scale*halfStrip<<")"<< std::endl;
197 
198  return phi;
199 }
200 
203 int AngleConverter::getProcessorPhi(unsigned int iProcessor, l1t::tftype part, const RPCDetId & rollId, const unsigned int &digi1, const unsigned int &digi2) const
204 {
205 
206  const double hsPhiPitch = 2*M_PI/nPhiBins;
207  const int dummy = nPhiBins;
208  int processor = iProcessor+1;
209  const RPCRoll* roll = _georpc->roll(rollId);
210  if (!roll) return dummy;
211 
212  double phi15deg = M_PI/3.*(processor-1)+M_PI/12.; // "0" is 15degree moved cyclicaly to each processor, note [0,2pi]
213  double stripPhi1 = (roll->toGlobal(roll->centreOfStrip((int)digi1))).phi(); // note [-pi,pi]
214  double stripPhi2 = (roll->toGlobal(roll->centreOfStrip((int)digi2))).phi(); // note [-pi,pi]
215 
216  // stripPhi from geometry is given in [-pi,pi] range.
217  // Keep like that for OMTFp1 [15-10deg,75deg] and OMTFp6 [-45-10deg,15deg].
218  // For OMTFp2..OMTFp5 move to [0,2pi] range
219  switch (processor) {
220  case 1: break;
221  case 6: {phi15deg -= 2*M_PI; break; }
222  default : { if (stripPhi1 < 0) stripPhi1 += 2*M_PI; if(stripPhi2 < 0 ) stripPhi2 += 2*M_PI; break; }
223  }
224 
225  // local angle in CSC halfStrip usnits
226  int halfStrip = lround ( ( (stripPhi1+stripPhi2)/2.-phi15deg)/hsPhiPitch );
227 
228  return halfStrip;
229 }
230 
231 int AngleConverter::getProcessorPhi(unsigned int iProcessor, l1t::tftype part, const RPCDetId & rollId, const unsigned int &digi) const
232 {
233 
234  const double hsPhiPitch = 2*M_PI/nPhiBins;
235  const int dummy = nPhiBins;
236  int processor = iProcessor+1;
237  const RPCRoll* roll = _georpc->roll(rollId);
238  if (!roll) return dummy;
239 
240  double phi15deg = M_PI/3.*(processor-1)+M_PI/12.; // "0" is 15degree moved cyclicaly to each processor, note [0,2pi]
241  double stripPhi = (roll->toGlobal(roll->centreOfStrip((int)digi))).phi(); // note [-pi,pi]
242 
243  // adjust [0,2pi] and [-pi,pi] to get deltaPhi difference properly
244  switch (processor) {
245  case 1: break;
246  case 6: {phi15deg -= 2*M_PI; break; }
247  default : {if (stripPhi < 0) stripPhi += 2*M_PI; break; }
248  }
249 
250  // local angle in CSC halfStrip usnits
251  int halfStrip = lround ( (stripPhi-phi15deg)/hsPhiPitch );
252 
253  return halfStrip;
254 }
257 int AngleConverter::getGlobalEta(unsigned int rawid,
258  const L1MuDTChambPhDigi &aDigi,
259  const L1MuDTChambThContainer *dtThDigis){
260 
261 
262  const DTChamberId baseid(aDigi.whNum(),aDigi.stNum(),aDigi.scNum()+1);
263 
264  // do not use this pointer for anything other than creating a trig geom
265  std::unique_ptr<DTChamber> chamb(const_cast<DTChamber*>(_geodt->chamber(baseid)));
266 
267  std::unique_ptr<DTTrigGeom> trig_geom( new DTTrigGeom(chamb.get(),false) );
268  chamb.release(); // release it here so no one gets funny ideas
269  // super layer one is the theta superlayer in a DT chamber
270  // station 4 does not have a theta super layer
271  // the BTI index from the theta trigger is an OR of some BTI outputs
272  // so, we choose the BTI that's in the middle of the group
273  // as the BTI that we get theta from
274  // TODO:::::>>> need to make sure this ordering doesn't flip under wheel sign
275  const int NBTI_theta = ( (baseid.station() != 4) ? trig_geom->nCell(2) : trig_geom->nCell(3) );
276 
277 // const int bti_group = findBTIgroup(aDigi,dtThDigis);
278 // const unsigned bti_actual = bti_group*NBTI_theta/7 + NBTI_theta/14 + 1;
279 // DTBtiId thetaBTI;
280 // if ( baseid.station() != 4 && bti_group != -1) {
281 // thetaBTI = DTBtiId(baseid,2,bti_actual);
282 // } else {
283 // // since this is phi oriented it'll give us theta in the middle
284 // // of the chamber
285 // thetaBTI = DTBtiId(baseid,3,1);
286 // }
287 // const GlobalPoint theta_gp = trig_geom->CMSPosition(thetaBTI);
288 // int iEta = theta_gp.eta()/2.61*240;
289 // return iEta;
290 
291  const L1MuDTChambThDigi *theta_segm = dtThDigis->chThetaSegm(aDigi.whNum(), aDigi.stNum(), aDigi.scNum(), aDigi.bxNum());
292  int bti_group = -1;
293  if (theta_segm) {
294  for(unsigned int i = 0; i < 7; ++i ) if(theta_segm->position(i) && bti_group<0) bti_group = i;
295  else if(theta_segm->position(i) && bti_group>-1) bti_group = 511;
296  }
297 
298  int iEta = 0;
299  if (bti_group == 511) iEta = 95;
300  else if ( bti_group == -1 && aDigi.stNum() == 1) iEta = 92;
301  else if ( bti_group == -1 && aDigi.stNum() == 2) iEta = 79;
302  else if ( bti_group == -1 && aDigi.stNum() == 3) iEta = 75;
303  else if (baseid.station() != 4 && bti_group >= 0) {
304 // bti_group = 6-bti_group;
305  unsigned bti_actual = bti_group*NBTI_theta/7 + NBTI_theta/14 + 1;
306  DTBtiId thetaBTI = DTBtiId(baseid,2,bti_actual);
307  GlobalPoint theta_gp = trig_geom->CMSPosition(thetaBTI);
308  iEta = etaVal2Code( fabs(theta_gp.eta()) );
309  }
310  int signEta = sgn(aDigi.whNum());
311  iEta *= signEta;
312  return iEta;
313 }
314 
317 int AngleConverter::getGlobalEta(unsigned int rawid, const CSCCorrelatedLCTDigi &aDigi){
318 
322 
323 
324  // alot of this is transcription and consolidation of the CSC
325  // global phi calculation code
326  // this works directly with the geometry
327  // rather than using the old phi luts
328  const CSCDetId id(rawid);
329  // we should change this to weak_ptrs at some point
330  // requires introducing std::shared_ptrs to geometry
331  std::unique_ptr<const CSCChamber> chamb(_geocsc->chamber(id));
332  std::unique_ptr<const CSCLayerGeometry> layer_geom(
333  chamb->layer(CSCConstants::KEY_ALCT_LAYER)->geometry()
334  );
335  std::unique_ptr<const CSCLayer> layer(
336  chamb->layer(CSCConstants::KEY_ALCT_LAYER)
337  );
338 
339  const uint16_t halfstrip = aDigi.getStrip();
340  const uint16_t pattern = aDigi.getPattern();
341  const uint16_t keyWG = aDigi.getKeyWG();
342  //const unsigned maxStrips = layer_geom->numberOfStrips();
343 
344  // so we can extend this later
345  // assume TMB2007 half-strips only as baseline
346  double offset = 0.0;
347  switch(1) {
348  case 1:
349  offset = CSCPatternLUT::get2007Position(pattern);
350  }
351  const unsigned halfstrip_offs = unsigned(0.5 + halfstrip + offset);
352  const unsigned strip = halfstrip_offs/2 + 1; // geom starts from 1
353 
354  // the rough location of the hit at the ALCT key layer
355  // we will refine this using the half strip information
356  const LocalPoint coarse_lp =
357  layer_geom->stripWireGroupIntersection(strip,keyWG);
358  const GlobalPoint coarse_gp = layer->surface().toGlobal(coarse_lp);
359 
360  // the strip width/4.0 gives the offset of the half-strip
361  // center with respect to the strip center
362  const double hs_offset = layer_geom->stripPhiPitch()/4.0;
363 
364  // determine handedness of the chamber
365  const bool ccw = isCSCCounterClockwise(layer);
366  // we need to subtract the offset of even half strips and add the odd ones
367  const double phi_offset = ( ( halfstrip_offs%2 ? 1 : -1)*
368  ( ccw ? -hs_offset : hs_offset ) );
369 
370  // the global eta calculation uses the middle of the strip
371  // so no need to increment it
372  const GlobalPoint final_gp( GlobalPoint::Polar( coarse_gp.theta(),
373  (coarse_gp.phi().value() +
374  phi_offset),
375  coarse_gp.mag() ) );
376  // release ownership of the pointers
377  chamb.release();
378  layer_geom.release();
379  layer.release();
380 
381 // std::cout <<id<<" st: " << id.station()<< "ri: "<<id.ring()<<" eta: " << final_gp.eta()
382 // <<" etaCode_simple: " << etaVal2Code( final_gp.eta() )<< " KW: "<<keyWG <<" etaKeyWG2Code: "<<etaKeyWG2Code(id,keyWG)<< std::endl;
383 // int station = (id.endcap()==1) ? id.station() : -id.station();
384 // std::cout <<"ETA_CSC: " << station <<" "<<id.ring()<<" "<< final_gp.eta()<<" "<<keyWG <<" "<< etaKeyWG2Code(id,keyWG) << std::endl;
385 
386  return etaKeyWG2Code(id,keyWG);
387 
388 // return etaVal2Code( final_gp.eta() );
389 // int iEta = final_gp.eta()/2.61*240;
390 // return iEta;
391 }
394 int AngleConverter::getGlobalEta(unsigned int rawid, const unsigned int &strip){
395 
396  const RPCDetId id(rawid);
397  std::unique_ptr<const RPCRoll> roll(_georpc->roll(id));
398  const LocalPoint lp = roll->centreOfStrip((int)strip);
399  const GlobalPoint gp = roll->toGlobal(lp);
400  roll.release();
401 
402  return etaVal2Code(gp.eta());
403 // float iEta = gp.eta()/2.61*240;
404 // return iEta;
405 
406 }
409 bool AngleConverter::
410 isCSCCounterClockwise(const std::unique_ptr<const CSCLayer>& layer) const {
411  const int nStrips = layer->geometry()->numberOfStrips();
412  const double phi1 = layer->centerOfStrip(1).phi();
413  const double phiN = layer->centerOfStrip(nStrips).phi();
414  return ( (std::abs(phi1 - phiN) < M_PI && phi1 >= phiN) ||
415  (std::abs(phi1 - phiN) >= M_PI && phi1 < phiN) );
416 }
420  const L1MuDTChambThContainer *dtThDigis){
421 
422  int bti_group = -1;
423 
424  const L1MuDTChambThDigi *theta_segm = dtThDigis->chThetaSegm(aDigi.whNum(),
425  aDigi.stNum(),
426  aDigi.scNum(),
427  aDigi.bxNum());
428  if(!theta_segm) return bti_group;
429 
430  for(unsigned int i = 0; i < 7; ++i ){
431  if(theta_segm->position(i) && bti_group<0) bti_group = i;
435  else if(theta_segm->position(i) && bti_group>-1) return -1;
436  }
437 
438  return bti_group;
439 }
int chamber() const
Definition: CSCDetId.h:68
int getStrip() const
return the key halfstrip from 0,159
unsigned long long cacheIdentifier() const
LocalPoint centreOfStrip(int strip) const
Definition: RPCRoll.cc:52
float sgn(float val)
Definition: FWPFMaths.cc:9
GlobalPoint toGlobal(const Local2DPoint &lp) const
Conversion to the global R.F. from the R.F. of the GeomDet.
Definition: GeomDet.h:54
Geom::Phi< T > phi() const
Definition: PV3DBase.h:69
int getGlobalEta(unsigned int rawid, const L1MuDTChambPhDigi &aDigi, const L1MuDTChambThContainer *dtThDigis)
Convert local eta coordinate to global digital microGMT scale.
unsigned long long _geom_cache_id
int position(const int i) const
Geom::Theta< T > theta() const
Definition: PV3DBase.h:75
int endcap() const
Definition: CSCDetId.h:93
unsigned long long _geom_cache_id
int getProcessorPhi(unsigned int iProcessor, l1t::tftype part, const L1MuDTChambPhDigi &digi) const
float stripPhiPitch() const
T mag() const
Definition: PV3DBase.h:67
const CSCChamberSpecs * specs() const
Definition: CSCChamber.h:42
void get(HolderT &iHolder) const
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
const CSCLayer * layer(CSCDetId id) const
Return the layer corresponding to the given id.
Definition: CSCChamber.cc:39
const int findBTIgroup(const L1MuDTChambPhDigi &aDigi, const L1MuDTChambThContainer *dtThDigis)
Find BTI group.
bool isCSCCounterClockwise(const std::unique_ptr< const CSCLayer > &layer) const
Check orientation of strips in given CSC chamber.
Definition: L1Track.h:19
#define M_PI
unsigned int nPhiBins
Number of phi bins along 2Pi.
int ring() const
Definition: CSCDetId.h:75
short int zendcap() const
Definition: CSCDetId.h:100
GlobalPoint centerOfStrip(int strip) const
Definition: CSCLayer.cc:4
static double get2007Position(int pattern)
part
Definition: HCALResponse.h:20
const T & get() const
Definition: EventSetup.h:56
const CSCChamber * chamber(CSCDetId id) const
Return the chamber corresponding to given DetId.
Definition: CSCGeometry.cc:118
L1MuDTChambThDigi const * chThetaSegm(int wheel, int stat, int sect, int bx) const
const DTChamber * chamber(DTChamberId id) const
Return a DTChamber given its id.
Definition: DTGeometry.cc:100
T eta() const
Definition: PV3DBase.h:76
int getPattern() const
return pattern
edm::ESHandle< CSCGeometry > _geocsc
void checkAndUpdateGeometry(const edm::EventSetup &, unsigned int)
Update the Geometry with current Event Setup.
int station() const
Definition: CSCDetId.h:86
edm::ESHandle< RPCGeometry > _georpc
long double T
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:40
int getKeyWG() const
return the key wire group. counts from 0.
const RPCRoll * roll(RPCDetId id) const
Return a roll given its id.
Definition: RPCGeometry.cc:75
edm::ESHandle< DTGeometry > _geodt