CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
L1GctMet.cc
Go to the documentation of this file.
2 
4 
5 #include <math.h>
6 
7 L1GctMet::L1GctMet(const unsigned ex, const unsigned ey, const L1GctMet::metAlgoType algo) :
8  m_exComponent(ex),
9  m_eyComponent(ey),
10  m_algoType(algo),
11  m_bitShift(0),
12  m_htMissLut(new L1GctHtMissLut())
13 { }
14 
16  m_exComponent(ex),
17  m_eyComponent(ey),
18  m_algoType(algo),
19  m_bitShift(0),
20  m_htMissLut(new L1GctHtMissLut())
21 { }
22 
24 
25 // the Etmiss algorithm - external entry point
28 {
30  etmiss_internal algoResult;
31  switch (m_algoType)
32  {
33  case cordicTranslate:
35  break;
36 
37  case useHtMissLut:
39  break;
40 
41  case oldGct:
42  algoResult = oldGctAlgo (m_exComponent.value(), m_eyComponent.value());
43  break;
44 
45  case floatingPoint:
47  break;
48 
49  default:
50  algoResult.mag = 0;
51  algoResult.phi = 0;
52  break;
53  }
54 
55  // The parameter m_bitShift allows us to discard additional LSB
56  // in order to change the output scale.
57  result.mag.setValue(algoResult.mag>>(m_bitShift));
58  result.phi.setValue(algoResult.phi);
59 
60  result.mag.setOverFlow( result.mag.overFlow() || inputOverFlow() );
61 
62  return result;
63 
64 }
65 
66 void L1GctMet::setExComponent(const unsigned ex) {
68  setExComponent(temp);
69 }
70 
71 void L1GctMet::setEyComponent(const unsigned ey) {
73  setEyComponent(temp);
74 }
75 
76 // private member functions - the different algorithms:
77 
79 L1GctMet::cordicTranslateAlgo (const int ex, const int ey, const bool of) const
80 {
81  //---------------------------------------------------------------------------------
82  //
83  // This is an implementation of the CORDIC algorithm (COordinate Rotation for DIgital Computers)
84  //
85  // Starting from an initial two-component vector ex, ey, we perform successively smaller rotations
86  // to transform the y component to zero. At the end of the procedure, the x component is the magnitude
87  // of the original vector, scaled by a known constant factor. The azimuth angle phi is the sum of the
88  // rotations applied.
89  //
90  // The algorithm can be used in a number of different variants for calculation of trigonometric
91  // and hyperbolic functions as well as exponentials, logarithms and square roots. This variant
92  // is called the "vector translation" mode in the Xilinx documentation.
93  //
94  // Original references:
95  // Volder, J., "The CORDIC Trigonometric Computing Technique" IRE Trans. Electronic Computing, Vol.
96  // EC-8, Sept. 1959, pp330-334
97  // Walther, J.S., "A Unified Algorithm for Elementary Functions," Spring Joint computer conf., 1971,
98  // proc., pp379-385
99  //
100  // Other information sources: http://www.xilinx.com/support/documentation/ip_documentation/cordic.pdf;
101  // http://www.fpga-guru.com/files/crdcsrvy.pdf; and http://en.wikipedia.org/wiki/CORDIC
102  //
103  //---------------------------------------------------------------------------------
104 
106 
107  static const int of_val = 0x1FFF; // set components to 8191 (decimal) if there's an overflow on the input
108 
109  static const int n_iterations = 6;
110  // The angle units here are 1/32 of a 5 degree bin.
111  // So a 90 degree rotation is 32*18=576 or 240 hex.
112  const int cordic_angles[n_iterations] = { 0x120, 0x0AA, 0x05A, 0x02E, 0x017, 0x00B };
113  const int cordic_starting_angle_090 = 0x240;
114  const int cordic_starting_angle_270 = 0x6C0;
115  const int cordic_angle_360 = 0x900;
116 
117  const int cordic_scale_factor = 0x26E; // decimal 622
118 
119  int x, y;
120  int dx,dy;
121  int z;
122 
123  if (of) {
124  x = of_val;
125  y = -of_val;
126  z = cordic_starting_angle_090;
127  } else {
128  if (ey>=0) {
129  x = ey;
130  y = -ex;
131  z = cordic_starting_angle_090;
132  } else {
133  x = -ey;
134  y = ex;
135  z = cordic_starting_angle_270;
136  }
137  }
138 
139  for (int i=0; i<n_iterations; i++) {
140  dx = cordicShiftAndRoundBits (y,i);
141  dy = cordicShiftAndRoundBits (x,i);
142  if (y>=0) {
143  x = x + dx;
144  y = y - dy;
145  z = z + cordic_angles[i];
146  } else {
147  x = x - dx;
148  y = y + dy;
149  z = z - cordic_angles[i];
150  }
151  }
152 
153  int scaled_magnitude = x * cordic_scale_factor;
154  int adjusted_angle = ( (z < 0) ? (z + cordic_angle_360) : z ) % cordic_angle_360;
155  result.mag = scaled_magnitude >> 10;
156  result.phi = adjusted_angle >> 5;
157  if (result.mag > (unsigned) of_val) result.mag = (unsigned) of_val;
158  return result;
159 }
160 
161 int L1GctMet::cordicShiftAndRoundBits (const int e, const unsigned nBits) const
162 {
163  int r;
164  if (nBits==0) {
165  r = e;
166  } else {
167  r = (((e>>(nBits-1)) + 1)>>1);
168  }
169  return r;
170 }
171 
172 
174 L1GctMet::useHtMissLutAlgo (const int ex, const int ey, const bool of) const
175 {
176  // The firmware discards the LSB of the input values, before forming
177  // the address for the LUT. We do the same here.
178  static const int maxComponent = 1<<L1GctHtMissLut::kHxOrHyMissComponentNBits;
179  static const int componentMask = maxComponent-1;
180  static const int maxPosComponent = componentMask >> 1;
181 
182  static const int maxInput = 1<<(L1GctHtMissLut::kHxOrHyMissComponentNBits+kExOrEyMissComponentShift-1);
183 
184  static const unsigned resultMagMask = (1<<L1GctHtMissLut::kHtMissMagnitudeNBits) - 1;
185  static const unsigned resultPhiMask = (1<<L1GctHtMissLut::kHtMissAngleNBits) - 1;
186 
188 
189  if (m_htMissLut == 0) {
190 
191  result.mag = 0;
192  result.phi = 0;
193 
194  } else {
195 
196  // Extract the bit fields of the input components to be used for the LUT address
197  int hxCompBits = (ex >> kExOrEyMissComponentShift) & componentMask;
198  int hyCompBits = (ey >> kExOrEyMissComponentShift) & componentMask;
199 
200  if (of || (abs(ex) >= maxInput) || (abs(ey) >= maxInput)) {
201  hxCompBits = maxPosComponent;
202  hyCompBits = maxPosComponent;
203  }
204 
205  // Perform the table lookup to get the missing Ht magnitude and phi
206  uint16_t lutAddress = static_cast<uint16_t> ( (hxCompBits << L1GctHtMissLut::kHxOrHyMissComponentNBits) | hyCompBits );
207 
208  uint16_t lutData = m_htMissLut->lutValue(lutAddress);
209 
210  result.mag = static_cast<unsigned>(lutData>>L1GctHtMissLut::kHtMissAngleNBits) & resultMagMask;
211  result.phi = static_cast<unsigned>(lutData) & resultPhiMask;
212 
213  }
214 
215  return result;
216 }
217 
219 L1GctMet::oldGctAlgo (const int ex, const int ey) const
220 {
221  //---------------------------------------------------------------------------------
222  //
223  // Calculates magnitude and direction of missing Et, given measured Ex and Ey.
224  //
225  // The algorithm used is suitable for implementation in hardware, using integer
226  // multiplication, addition and comparison and bit shifting operations.
227  //
228  // Proceed in two stages. The first stage gives a result that lies between
229  // 92% and 100% of the true Et, with the direction measured in 45 degree bins.
230  // The final precision depends on the number of factors used in corrFact.
231  // The present version with eleven factors gives a precision of 1% on Et, and
232  // finds the direction to the nearest 5 degrees.
233  //
234  //---------------------------------------------------------------------------------
236 
237  unsigned eneCoarse, phiCoarse;
238  unsigned eneCorect, phiCorect;
239 
240  const unsigned root2fact = 181;
241  const unsigned corrFact[11] = {24, 39, 51, 60, 69, 77, 83, 89, 95, 101, 106};
242  const unsigned corrDphi[11] = { 0, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4};
243 
244  std::vector<bool> s(3);
245  unsigned Mx, My, Mw;
246 
247  unsigned Dx, Dy;
248  unsigned eFact;
249 
250  unsigned b,phibin;
251  bool midphi=false;
252 
253  // Here's the coarse calculation, with just one multiply operation
254  //
255  My = static_cast<unsigned>(abs(ey));
256  Mx = static_cast<unsigned>(abs(ex));
257  Mw = (((Mx+My)*root2fact)+0x80)>>8;
258 
259  s.at(0) = (ey<0);
260  s.at(1) = (ex<0);
261  s.at(2) = (My>Mx);
262 
263  phibin = 0; b = 0;
264  for (int i=0; i<3; i++) {
265  if (s.at(i)) { b=1-b;} phibin = 2*phibin + b;
266  }
267 
268  eneCoarse = std::max(std::max(Mx, My), Mw);
269  phiCoarse = phibin*9;
270 
271  // For the fine calculation we multiply both input components
272  // by all the factors in the corrFact list in order to find
273  // the required corrections to the energy and angle
274  //
275  for (eFact=0; eFact<10; eFact++) {
276  Dx = (Mx*corrFact[eFact])>>8;
277  Dy = (My*corrFact[eFact])>>8;
278  if ((Dx>=My) || (Dy>=Mx)) {midphi=false; break;}
279  if ((Mx+Dx)>=(My-Dy) && (My+Dy)>=(Mx-Dx)) {midphi=true; break;}
280  }
281  eneCorect = (eneCoarse*(128+eFact))>>7;
282  if (midphi ^ (b==1)) {
283  phiCorect = phiCoarse + 8 - corrDphi[eFact];
284  } else {
285  phiCorect = phiCoarse + corrDphi[eFact];
286  }
287 
288  // Store the result of the calculation
289  //
290  result.mag = eneCorect;
291  result.phi = phiCorect;
292 
293  return result;
294 }
295 
297 L1GctMet::floatingPointAlgo (const int ex, const int ey) const
298 {
299 
301 
302  double fx = static_cast<double>(ex);
303  double fy = static_cast<double>(ey);
304  double fmag = sqrt(fx*fx + fy*fy);
305  double fphi = 36.*atan2(fy, fx)/M_PI;
306 
307  result.mag = static_cast<unsigned>(fmag);
308  if (fphi>=0) {
309  result.phi = static_cast<unsigned>(fphi);
310  } else {
311  result.phi = static_cast<unsigned>(fphi+72.);
312  }
313 
314  return result;
315 
316 }
317 
319 {
320  m_htMissLut->setEtScale(fn);
321 }
322 
323 void L1GctMet::setEtComponentLsb(const double lsb)
324 {
325  m_htMissLut->setExEyLsb( lsb * static_cast<double>( 1<<kExOrEyMissComponentShift ) );
326 }
327 
329 {
330  return m_htMissLut->etScale();
331 }
332 
333 const double L1GctMet::componentLsb() const
334 {
335  return m_htMissLut->componentLsb();
336 }
337 
340 const bool L1GctMet::inputOverFlow() const
341 {
343 
344  if (m_algoType == useHtMissLut) {
345  static const int maxComponentInput = ( 1 << (L1GctHtMissLut::kHxOrHyMissComponentNBits+kExOrEyMissComponentShift-1) ) - 1;
346 
347  // Emulate the (symmetric) overflow condition used in the firmware
348  result |= (m_exComponent.value() > maxComponentInput) || (m_exComponent.value() < -maxComponentInput) ||
349  (m_eyComponent.value() > maxComponentInput) || (m_eyComponent.value() < -maxComponentInput);
350  }
351 
352  return result;
353 }
354 
bool overFlow() const
access overflow
int i
Definition: DBlmapReader.cc:9
etComponentType m_exComponent
Definition: L1GctMet.h:84
void setEtScale(const L1CaloEtScale *const fn)
Set the functions.
void setOverFlow(bool oflow)
set the overflow bit
L1GctMet(const unsigned ex=0, const unsigned ey=0, const metAlgoType algo=cordicTranslate)
Definition: L1GctMet.cc:7
~L1GctMet()
Definition: L1GctMet.cc:23
const bool inputOverFlow() const
Definition: L1GctMet.cc:340
const double componentLsb() const
Definition: L1GctMet.cc:333
etMissPhiType phi
Definition: L1GctMet.h:32
etmiss_internal useHtMissLutAlgo(const int ex, const int ey, const bool of) const
Definition: L1GctMet.cc:174
LUT for conversion of Ht components x and y to magnitude and angle.
void setEyComponent(const unsigned ey)
Definition: L1GctMet.cc:71
void setExComponent(const unsigned ex)
Definition: L1GctMet.cc:66
etmiss_internal oldGctAlgo(const int ex, const int ey) const
Definition: L1GctMet.cc:219
tuple result
Definition: mps_fire.py:95
void setEtScale(const L1CaloEtScale *const fn)
Definition: L1GctMet.cc:318
T sqrt(T t)
Definition: SSEVec.h:18
int cordicShiftAndRoundBits(const int e, const unsigned nBits) const
Definition: L1GctMet.cc:161
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
void setExEyLsb(const double lsb)
const double componentLsb() const
#define M_PI
L1GctHtMissLut * m_htMissLut
Definition: L1GctMet.h:89
etmiss_internal cordicTranslateAlgo(const int ex, const int ey, const bool of) const
Definition: L1GctMet.cc:79
etComponentType m_eyComponent
Definition: L1GctMet.h:85
int value() const
access value as signed int
const L1CaloEtScale * etScale() const
Definition: L1GctMet.cc:328
etmiss_vec metVector() const
Definition: L1GctMet.cc:27
etmiss_internal floatingPointAlgo(const int ex, const int ey) const
Definition: L1GctMet.cc:297
double b
Definition: hdecay.h:120
metAlgoType
Definition: L1GctMet.h:24
const L1CaloEtScale * etScale() const
Return the Lut functions and parameters.
void setValue(unsigned value)
Set value from unsigned.
uint16_t lutValue(const uint16_t lutAddress) const
Access the look-up table contents for a given Address.
Definition: L1GctLut.h:104
etMissType mag
Definition: L1GctMet.h:31
bool overFlow() const
access overflow
metAlgoType m_algoType
Definition: L1GctMet.h:86
unsigned short m_bitShift
Definition: L1GctMet.h:87
void setEtComponentLsb(const double lsb)
Definition: L1GctMet.cc:323