CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
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 
94 AngleConverter::AngleConverter(): _geom_cache_id(0ULL) { }
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 
142  int phi = static_cast<int>(phiDT*scale) + offsetLoc;
143 
144  return phi;
145 }
148 int AngleConverter::getProcessorPhi(unsigned int iProcessor, l1t::tftype part, const CSCDetId & csc, const CSCCorrelatedLCTDigi &digi) const
149 {
150 
151  const double hsPhiPitch = 2*M_PI/nPhiBins;
152  const int dummy = nPhiBins;
153  int processor= iProcessor+1; // FIXME: get from OMTF name when available
154  int posneg = (part==l1t::tftype::omtf_pos) ? 1 : -1; // FIXME: get from OMTF name
155 
156 
157 
158  // filter out chambers not connected to OMTF board
159  // FIXME: temporary - use Connections or relay that filtering done before.
160  if (posneg != csc.zendcap()) return dummy;
161  if ( csc.ring() != 3 && !(csc.ring()==2 && (csc.station()==2 || csc.station()==3 || csc.station()==1)) ) return dummy;
162  if (processor !=6) {
163  if (csc.chamber() < (processor-1)*6 + 2) return dummy;
164  if (csc.chamber() > (processor-1)*6 + 8) return dummy;
165  } else {
166  if (csc.chamber() > 2 && csc.chamber() < 32) return dummy;
167  }
168 
169  //
170  // assign number 0..6, consecutive processor for a processor
171  //
172  //int ichamber = (csc.chamber()-2-6*(processor-1));
173  //if (ichamber < 0) ichamber += 36;
174 
175  //
176  // get offset for each chamber.
177  // FIXME: These parameters depends on processor and chamber only so may be precomputed and put in map
178  //
179  const CSCChamber* chamber = _geocsc->chamber(csc);
180  const CSCChamberSpecs* cspec = chamber->specs();
181  const CSCLayer* layer = chamber->layer(3);
182  int order = ( layer->centerOfStrip(2).phi() - layer->centerOfStrip(1).phi()> 0) ? 1 : -1;
183  double stripPhiPitch = cspec->stripPhiPitch();
184  double scale = fabs(stripPhiPitch/hsPhiPitch/2.); if ( fabs(scale-1.) < 0.0002) scale=1.;
185  double phi15deg = M_PI/3.*(processor-1)+M_PI/12.;
186  double phiHalfStrip0 = layer->centerOfStrip(10).phi() - order*9*stripPhiPitch - order*stripPhiPitch/4.;
187  if ( processor==6 || phiHalfStrip0<0) phiHalfStrip0 += 2*M_PI;
188  int offsetLoc = lround( (phiHalfStrip0-phi15deg)/hsPhiPitch );
189 
190  int halfStrip = digi.getStrip(); // returns halfStrip 0..159
191  //FIXME: to be checked (only important for ME1/3) keep more bits for offset, truncate at the end
192  int phi = offsetLoc + order*scale*halfStrip;
193 
194  return phi;
195 }
196 
199 int AngleConverter::getProcessorPhi(unsigned int iProcessor, l1t::tftype part, const RPCDetId & rollId, const unsigned int &digi) const
200 {
201 
202  const double hsPhiPitch = 2*M_PI/nPhiBins;
203  const int dummy = nPhiBins;
204  int processor = iProcessor+1;
205  const RPCRoll* roll = _georpc->roll(rollId);
206  if (!roll) return dummy;
207 
208  double phi15deg = M_PI/3.*(processor-1)+M_PI/12.; // "0" is 15degree moved cyclicaly to each processor, note [0,2pi]
209  double stripPhi = (roll->toGlobal(roll->centreOfStrip((int)digi))).phi(); // note [-pi,pi]
210 
211  // adjust [0,2pi] and [-pi,pi] to get deltaPhi difference properly
212  switch (processor) {
213  case 1: break;
214  case 6: {phi15deg -= 2*M_PI; break; }
215  default : {if (stripPhi < 0) stripPhi += 2*M_PI; break; }
216  }
217 
218  // local angle in CSC halfStrip usnits
219  int halfStrip = lround ( (stripPhi-phi15deg)/hsPhiPitch );
220 
221  return halfStrip;
222 }
225 int AngleConverter::getGlobalEta(unsigned int rawid,
226  const L1MuDTChambPhDigi &aDigi,
227  const L1MuDTChambThContainer *dtThDigis){
228 
229 
230  const DTChamberId baseid(aDigi.whNum(),aDigi.stNum(),aDigi.scNum()+1);
231 
232  // do not use this pointer for anything other than creating a trig geom
233  std::unique_ptr<DTChamber> chamb(const_cast<DTChamber*>(_geodt->chamber(baseid)));
234 
235  std::unique_ptr<DTTrigGeom> trig_geom( new DTTrigGeom(chamb.get(),false) );
236  chamb.release(); // release it here so no one gets funny ideas
237  // super layer one is the theta superlayer in a DT chamber
238  // station 4 does not have a theta super layer
239  // the BTI index from the theta trigger is an OR of some BTI outputs
240  // so, we choose the BTI that's in the middle of the group
241  // as the BTI that we get theta from
242  // TODO:::::>>> need to make sure this ordering doesn't flip under wheel sign
243  const int NBTI_theta = ( (baseid.station() != 4) ?
244  trig_geom->nCell(2) : trig_geom->nCell(3) );
245  const int bti_group = findBTIgroup(aDigi,dtThDigis);
246  const unsigned bti_actual = bti_group*NBTI_theta/7 + NBTI_theta/14 + 1;
247  DTBtiId thetaBTI;
248  if ( baseid.station() != 4 && bti_group != -1) {
249  thetaBTI = DTBtiId(baseid,2,bti_actual);
250  } else {
251  // since this is phi oriented it'll give us theta in the middle
252  // of the chamber
253  thetaBTI = DTBtiId(baseid,3,1);
254  }
255  const GlobalPoint theta_gp = trig_geom->CMSPosition(thetaBTI);
256  return etaVal2Code(theta_gp.eta());
257 // int iEta = theta_gp.eta()/2.61*240;
258 // return iEta;
259 }
262 int AngleConverter::getGlobalEta(unsigned int rawid, const CSCCorrelatedLCTDigi &aDigi){
263 
267 
268 
269  // alot of this is transcription and consolidation of the CSC
270  // global phi calculation code
271  // this works directly with the geometry
272  // rather than using the old phi luts
273  const CSCDetId id(rawid);
274  // we should change this to weak_ptrs at some point
275  // requires introducing std::shared_ptrs to geometry
276  std::unique_ptr<const CSCChamber> chamb(_geocsc->chamber(id));
277  std::unique_ptr<const CSCLayerGeometry> layer_geom(
278  chamb->layer(CSCConstants::KEY_ALCT_LAYER)->geometry()
279  );
280  std::unique_ptr<const CSCLayer> layer(
281  chamb->layer(CSCConstants::KEY_ALCT_LAYER)
282  );
283 
284  const uint16_t halfstrip = aDigi.getStrip();
285  const uint16_t pattern = aDigi.getPattern();
286  const uint16_t keyWG = aDigi.getKeyWG();
287  //const unsigned maxStrips = layer_geom->numberOfStrips();
288 
289  // so we can extend this later
290  // assume TMB2007 half-strips only as baseline
291  double offset = 0.0;
292  switch(1) {
293  case 1:
294  offset = CSCPatternLUT::get2007Position(pattern);
295  }
296  const unsigned halfstrip_offs = unsigned(0.5 + halfstrip + offset);
297  const unsigned strip = halfstrip_offs/2 + 1; // geom starts from 1
298 
299  // the rough location of the hit at the ALCT key layer
300  // we will refine this using the half strip information
301  const LocalPoint coarse_lp =
302  layer_geom->stripWireGroupIntersection(strip,keyWG);
303  const GlobalPoint coarse_gp = layer->surface().toGlobal(coarse_lp);
304 
305  // the strip width/4.0 gives the offset of the half-strip
306  // center with respect to the strip center
307  const double hs_offset = layer_geom->stripPhiPitch()/4.0;
308 
309  // determine handedness of the chamber
310  const bool ccw = isCSCCounterClockwise(layer);
311  // we need to subtract the offset of even half strips and add the odd ones
312  const double phi_offset = ( ( halfstrip_offs%2 ? 1 : -1)*
313  ( ccw ? -hs_offset : hs_offset ) );
314 
315  // the global eta calculation uses the middle of the strip
316  // so no need to increment it
317  const GlobalPoint final_gp( GlobalPoint::Polar( coarse_gp.theta(),
318  (coarse_gp.phi().value() +
319  phi_offset),
320  coarse_gp.mag() ) );
321  // release ownership of the pointers
322  chamb.release();
323  layer_geom.release();
324  layer.release();
325 
326 // std::cout <<id<<" st: " << id.station()<< "ri: "<<id.ring()<<" eta: " << final_gp.eta()
327 // <<" etaCode_simple: " << etaVal2Code( final_gp.eta() )<< " KW: "<<keyWG <<" etaKeyWG2Code: "<<etaKeyWG2Code(id,keyWG)<< std::endl;
328 // int station = (id.endcap()==1) ? id.station() : -id.station();
329 // std::cout <<"ETA_CSC: " << station <<" "<<id.ring()<<" "<< final_gp.eta()<<" "<<keyWG <<" "<< etaKeyWG2Code(id,keyWG) << std::endl;
330 
331  return etaKeyWG2Code(id,keyWG);
332 
333 // return etaVal2Code( final_gp.eta() );
334 // int iEta = final_gp.eta()/2.61*240;
335 // return iEta;
336 }
339 int AngleConverter::getGlobalEta(unsigned int rawid, const unsigned int &strip){
340 
341  const RPCDetId id(rawid);
342  std::unique_ptr<const RPCRoll> roll(_georpc->roll(id));
343  const LocalPoint lp = roll->centreOfStrip((int)strip);
344  const GlobalPoint gp = roll->toGlobal(lp);
345  roll.release();
346 
347  return etaVal2Code(gp.eta());
348 // float iEta = gp.eta()/2.61*240;
349 // return iEta;
350 
351 }
354 bool AngleConverter::
355 isCSCCounterClockwise(const std::unique_ptr<const CSCLayer>& layer) const {
356  const int nStrips = layer->geometry()->numberOfStrips();
357  const double phi1 = layer->centerOfStrip(1).phi();
358  const double phiN = layer->centerOfStrip(nStrips).phi();
359  return ( (std::abs(phi1 - phiN) < M_PI && phi1 >= phiN) ||
360  (std::abs(phi1 - phiN) >= M_PI && phi1 < phiN) );
361 }
365  const L1MuDTChambThContainer *dtThDigis){
366 
367  int bti_group = -1;
368 
369  const L1MuDTChambThDigi *theta_segm = dtThDigis->chThetaSegm(aDigi.whNum(),
370  aDigi.stNum(),
371  aDigi.scNum(),
372  aDigi.bxNum());
373  if(!theta_segm) return bti_group;
374 
375  for(unsigned int i = 0; i < 7; ++i ){
376  if(theta_segm->position(i) && bti_group<0) bti_group = i;
380  else if(theta_segm->position(i) && bti_group>-1) return -1;
381  }
382 
383  return bti_group;
384 }
int chamber() const
Definition: CSCDetId.h:68
int getStrip() const
return the key halfstrip from 0,159
unsigned long long cacheIdentifier() const
int i
Definition: DBlmapReader.cc:9
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:52
double sign(double x)
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
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.
#define M_PI
unsigned int nPhiBins
Number of phi bins along 2Pi.
T value() const
Explicit access to value in case implicit conversion not OK.
Definition: Phi.h:38
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
L1MuDTChambThDigi const * chThetaSegm(int wheel, int stat, int sect, int bx) const
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
int getKeyWG() const
return the key wire group
edm::ESHandle< DTGeometry > _geodt