00001 #include "L1Trigger/GlobalCaloTrigger/interface/L1GctMet.h"
00002
00003 #include "L1Trigger/GlobalCaloTrigger/interface/L1GctHtMissLut.h"
00004
00005 #include <math.h>
00006
00007 L1GctMet::L1GctMet(const unsigned ex, const unsigned ey, const L1GctMet::metAlgoType algo) :
00008 m_exComponent(ex),
00009 m_eyComponent(ey),
00010 m_algoType(algo),
00011 m_bitShift(0),
00012 m_htMissLut(new L1GctHtMissLut())
00013 { }
00014
00015 L1GctMet::L1GctMet(const etComponentType& ex, const etComponentType& ey, const metAlgoType algo) :
00016 m_exComponent(ex),
00017 m_eyComponent(ey),
00018 m_algoType(algo),
00019 m_bitShift(0),
00020 m_htMissLut(new L1GctHtMissLut())
00021 { }
00022
00023 L1GctMet::~L1GctMet() {}
00024
00025
00026 L1GctMet::etmiss_vec
00027 L1GctMet::metVector () const
00028 {
00029 etmiss_vec result;
00030 etmiss_internal algoResult;
00031 switch (m_algoType)
00032 {
00033 case cordicTranslate:
00034 algoResult = cordicTranslateAlgo (m_exComponent.value(), m_eyComponent.value(), (m_exComponent.overFlow() || m_eyComponent.overFlow()) );
00035 break;
00036
00037 case useHtMissLut:
00038 algoResult = useHtMissLutAlgo (m_exComponent.value(), m_eyComponent.value(), (m_exComponent.overFlow() || m_eyComponent.overFlow()) );
00039 break;
00040
00041 case oldGct:
00042 algoResult = oldGctAlgo (m_exComponent.value(), m_eyComponent.value());
00043 break;
00044
00045 case floatingPoint:
00046 algoResult = floatingPointAlgo (m_exComponent.value(), m_eyComponent.value());
00047 break;
00048
00049 default:
00050 algoResult.mag = 0;
00051 algoResult.phi = 0;
00052 break;
00053 }
00054
00055
00056
00057 result.mag.setValue(algoResult.mag>>(m_bitShift));
00058 result.phi.setValue(algoResult.phi);
00059
00060 result.mag.setOverFlow( result.mag.overFlow() || inputOverFlow() );
00061
00062 return result;
00063
00064 }
00065
00066 void L1GctMet::setExComponent(const unsigned ex) {
00067 etComponentType temp(ex);
00068 setExComponent(temp);
00069 }
00070
00071 void L1GctMet::setEyComponent(const unsigned ey) {
00072 etComponentType temp(ey);
00073 setEyComponent(temp);
00074 }
00075
00076
00077
00078 L1GctMet::etmiss_internal
00079 L1GctMet::cordicTranslateAlgo (const int ex, const int ey, const bool of) const
00080 {
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105 etmiss_internal result;
00106
00107 static const int of_val = 0x1FFF;
00108
00109 static const int n_iterations = 6;
00110
00111
00112 const int cordic_angles[n_iterations] = { 0x120, 0x0AA, 0x05A, 0x02E, 0x017, 0x00B };
00113 const int cordic_starting_angle_090 = 0x240;
00114 const int cordic_starting_angle_270 = 0x6C0;
00115 const int cordic_angle_360 = 0x900;
00116
00117 const int cordic_scale_factor = 0x26E;
00118
00119 int x, y;
00120 int dx,dy;
00121 int z;
00122
00123 if (of) {
00124 x = of_val;
00125 y = -of_val;
00126 z = cordic_starting_angle_090;
00127 } else {
00128 if (ey>=0) {
00129 x = ey;
00130 y = -ex;
00131 z = cordic_starting_angle_090;
00132 } else {
00133 x = -ey;
00134 y = ex;
00135 z = cordic_starting_angle_270;
00136 }
00137 }
00138
00139 for (int i=0; i<n_iterations; i++) {
00140 dx = cordicShiftAndRoundBits (y,i);
00141 dy = cordicShiftAndRoundBits (x,i);
00142 if (y>=0) {
00143 x = x + dx;
00144 y = y - dy;
00145 z = z + cordic_angles[i];
00146 } else {
00147 x = x - dx;
00148 y = y + dy;
00149 z = z - cordic_angles[i];
00150 }
00151 }
00152
00153 int scaled_magnitude = x * cordic_scale_factor;
00154 int adjusted_angle = ( (z < 0) ? (z + cordic_angle_360) : z ) % cordic_angle_360;
00155 result.mag = scaled_magnitude >> 10;
00156 result.phi = adjusted_angle >> 5;
00157 if (result.mag > (unsigned) of_val) result.mag = (unsigned) of_val;
00158 return result;
00159 }
00160
00161 int L1GctMet::cordicShiftAndRoundBits (const int e, const unsigned nBits) const
00162 {
00163 int r;
00164 if (nBits==0) {
00165 r = e;
00166 } else {
00167 r = (((e>>(nBits-1)) + 1)>>1);
00168 }
00169 return r;
00170 }
00171
00172
00173 L1GctMet::etmiss_internal
00174 L1GctMet::useHtMissLutAlgo (const int ex, const int ey, const bool of) const
00175 {
00176
00177
00178 static const int maxComponent = 1<<L1GctHtMissLut::kHxOrHyMissComponentNBits;
00179 static const int componentMask = maxComponent-1;
00180 static const int maxPosComponent = componentMask >> 1;
00181
00182 static const int maxInput = 1<<(L1GctHtMissLut::kHxOrHyMissComponentNBits+kExOrEyMissComponentShift-1);
00183
00184 static const unsigned resultMagMask = (1<<L1GctHtMissLut::kHtMissMagnitudeNBits) - 1;
00185 static const unsigned resultPhiMask = (1<<L1GctHtMissLut::kHtMissAngleNBits) - 1;
00186
00187 etmiss_internal result;
00188
00189 if (m_htMissLut == 0) {
00190
00191 result.mag = 0;
00192 result.phi = 0;
00193
00194 } else {
00195
00196
00197 int hxCompBits = (ex >> kExOrEyMissComponentShift) & componentMask;
00198 int hyCompBits = (ey >> kExOrEyMissComponentShift) & componentMask;
00199
00200 if (of || (abs(ex) >= maxInput) || (abs(ey) >= maxInput)) {
00201 hxCompBits = maxPosComponent;
00202 hyCompBits = maxPosComponent;
00203 }
00204
00205
00206 uint16_t lutAddress = static_cast<uint16_t> ( (hxCompBits << L1GctHtMissLut::kHxOrHyMissComponentNBits) | hyCompBits );
00207
00208 uint16_t lutData = m_htMissLut->lutValue(lutAddress);
00209
00210 result.mag = static_cast<unsigned>(lutData>>L1GctHtMissLut::kHtMissAngleNBits) & resultMagMask;
00211 result.phi = static_cast<unsigned>(lutData) & resultPhiMask;
00212
00213 }
00214
00215 return result;
00216 }
00217
00218 L1GctMet::etmiss_internal
00219 L1GctMet::oldGctAlgo (const int ex, const int ey) const
00220 {
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235 etmiss_internal result;
00236
00237 unsigned eneCoarse, phiCoarse;
00238 unsigned eneCorect, phiCorect;
00239
00240 const unsigned root2fact = 181;
00241 const unsigned corrFact[11] = {24, 39, 51, 60, 69, 77, 83, 89, 95, 101, 106};
00242 const unsigned corrDphi[11] = { 0, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4};
00243
00244 std::vector<bool> s(3);
00245 unsigned Mx, My, Mw;
00246
00247 unsigned Dx, Dy;
00248 unsigned eFact;
00249
00250 unsigned b,phibin;
00251 bool midphi=false;
00252
00253
00254
00255 My = static_cast<unsigned>(abs(ey));
00256 Mx = static_cast<unsigned>(abs(ex));
00257 Mw = (((Mx+My)*root2fact)+0x80)>>8;
00258
00259 s.at(0) = (ey<0);
00260 s.at(1) = (ex<0);
00261 s.at(2) = (My>Mx);
00262
00263 phibin = 0; b = 0;
00264 for (int i=0; i<3; i++) {
00265 if (s.at(i)) { b=1-b;} phibin = 2*phibin + b;
00266 }
00267
00268 eneCoarse = std::max(std::max(Mx, My), Mw);
00269 phiCoarse = phibin*9;
00270
00271
00272
00273
00274
00275 for (eFact=0; eFact<10; eFact++) {
00276 Dx = (Mx*corrFact[eFact])>>8;
00277 Dy = (My*corrFact[eFact])>>8;
00278 if ((Dx>=My) || (Dy>=Mx)) {midphi=false; break;}
00279 if ((Mx+Dx)>=(My-Dy) && (My+Dy)>=(Mx-Dx)) {midphi=true; break;}
00280 }
00281 eneCorect = (eneCoarse*(128+eFact))>>7;
00282 if (midphi ^ (b==1)) {
00283 phiCorect = phiCoarse + 8 - corrDphi[eFact];
00284 } else {
00285 phiCorect = phiCoarse + corrDphi[eFact];
00286 }
00287
00288
00289
00290 result.mag = eneCorect;
00291 result.phi = phiCorect;
00292
00293 return result;
00294 }
00295
00296 L1GctMet::etmiss_internal
00297 L1GctMet::floatingPointAlgo (const int ex, const int ey) const
00298 {
00299
00300 etmiss_internal result;
00301
00302 double fx = static_cast<double>(ex);
00303 double fy = static_cast<double>(ey);
00304 double fmag = sqrt(fx*fx + fy*fy);
00305 double fphi = 36.*atan2(fy, fx)/M_PI;
00306
00307 result.mag = static_cast<unsigned>(fmag);
00308 if (fphi>=0) {
00309 result.phi = static_cast<unsigned>(fphi);
00310 } else {
00311 result.phi = static_cast<unsigned>(fphi+72.);
00312 }
00313
00314 return result;
00315
00316 }
00317
00318 void L1GctMet::setEtScale(const L1CaloEtScale* const fn)
00319 {
00320 m_htMissLut->setEtScale(fn);
00321 }
00322
00323 void L1GctMet::setEtComponentLsb(const double lsb)
00324 {
00325 m_htMissLut->setExEyLsb( lsb * static_cast<double>( 1<<kExOrEyMissComponentShift ) );
00326 }
00327
00328 const L1CaloEtScale* L1GctMet::etScale() const
00329 {
00330 return m_htMissLut->etScale();
00331 }
00332
00333 const double L1GctMet::componentLsb() const
00334 {
00335 return m_htMissLut->componentLsb();
00336 }
00337
00340 const bool L1GctMet::inputOverFlow() const
00341 {
00342 bool result = m_exComponent.overFlow() || m_eyComponent.overFlow();
00343
00344 if (m_algoType == useHtMissLut) {
00345 static const int maxComponentInput = ( 1 << (L1GctHtMissLut::kHxOrHyMissComponentNBits+kExOrEyMissComponentShift-1) ) - 1;
00346
00347
00348 result |= (m_exComponent.value() > maxComponentInput) || (m_exComponent.value() < -maxComponentInput) ||
00349 (m_eyComponent.value() > maxComponentInput) || (m_eyComponent.value() < -maxComponentInput);
00350 }
00351
00352 return result;
00353 }
00354