ATLAS_2012_I1119557.cc
Go to the documentation of this file.
00001 // -*- C++ -*- 00002 #include "Rivet/Analysis.hh" 00003 #include "Rivet/Projections/FastJets.hh" 00004 #include "Rivet/Projections/FinalState.hh" 00005 00006 namespace Rivet { 00007 00008 00009 namespace { // unnamed namespace 00010 // Forward declarations of calculator functions: implementations at bottom of file 00011 double getWidth(const Jet& jet); 00012 double getEcc(const Jet& jet); 00013 double getPFlow(const Jet& jet); 00014 double getAngularity(const Jet& jet); 00015 } 00016 00017 00018 class ATLAS_2012_I1119557 : public Analysis { 00019 public: 00020 00021 ATLAS_2012_I1119557() 00022 : Analysis("ATLAS_2012_I1119557") 00023 { } 00024 00025 00026 void init() { 00027 const FinalState fs; 00028 addProjection(fs, "FinalState"); 00029 00030 FastJets fj06(fs, FastJets::ANTIKT, 0.6); 00031 addProjection(fj06, "AntiKT06"); 00032 FastJets fj10(fs, FastJets::ANTIKT, 1.0); 00033 addProjection(fj10, "AntiKT10"); 00034 00035 for (size_t alg = 0; alg < 2; ++alg) { 00036 _hs_mass[alg] = bookHisto1D(1, alg+1, 1); 00037 _hs_width[alg] = bookHisto1D(2, alg+1, 1); 00038 /// @todo Commented eccentricity out for now: reinstate 00039 // _hs_eccentricity[alg] = bookHisto1D(3, alg+1, 1); 00040 } 00041 _h_planarFlow = bookHisto1D(4, 2, 1); 00042 _h_angularity = bookHisto1D(5, 1, 1); 00043 00044 } 00045 00046 00047 /// Perform the per-event analysis 00048 void analyze(const Event& event) { 00049 const double weight = event.weight(); 00050 Jets jetAr[2]; 00051 jetAr[0] = applyProjection<FastJets>(event, "AntiKT06").jetsByPt(300.*GeV, MAXDOUBLE, -2.0, 2.0); 00052 jetAr[1] = applyProjection<FastJets>(event, "AntiKT10").jetsByPt(300.*GeV, MAXDOUBLE, -2.0, 2.0); 00053 00054 for (size_t alg = 0; alg < 2; ++alg) { 00055 // Require at least one jet 00056 if (jetAr[alg].size() < 1) continue; 00057 00058 // The leading jet 00059 const Jet& jet = jetAr[alg][0]; 00060 const double m = jet.momentum().mass(); 00061 const double eta = jet.eta(); 00062 00063 _hs_mass[alg]->fill(m/GeV, weight); 00064 _hs_width[alg]->fill(getWidth(jet), weight); 00065 /// @todo Commented eccentricity out for now: reinstate 00066 // if (fabs(eta) < 0.7 && m > 100*GeV) _hs_eccentricity[alg]->fill(getEcc(jet), weight); 00067 00068 if (fabs(eta) < 0.7) { 00069 if (alg == 0 && inRange(m/GeV, 100., 130.)) _h_angularity->fill(getAngularity(jet), weight); 00070 if (alg == 1 && inRange(m/GeV, 130., 210.)) _h_planarFlow->fill(getPFlow(jet), weight); 00071 } 00072 } 00073 } 00074 00075 00076 /// Normalise histograms etc., after the run 00077 void finalize() { 00078 for (size_t alg = 0; alg < 2; ++alg) { 00079 normalize(_hs_mass[alg]); 00080 normalize(_hs_width[alg]); 00081 /// @todo Commented eccentricity out for now: reinstate 00082 // normalize(_hs_eccentricity[alg]); 00083 } 00084 normalize(_h_planarFlow); 00085 normalize(_h_angularity); 00086 } 00087 00088 00089 private: 00090 00091 Histo1DPtr _hs_mass[2]; 00092 Histo1DPtr _hs_width[2]; 00093 /// @todo Commented eccentricity out for now: reinstate 00094 // Histo1DPtr _hs_eccentricity[2]; 00095 Histo1DPtr _h_planarFlow; 00096 Histo1DPtr _h_angularity; 00097 }; 00098 00099 00100 DECLARE_RIVET_PLUGIN(ATLAS_2012_I1119557); 00101 00102 00103 00104 namespace { // unnamed namespace 00105 00106 // Adapted code from Lily 00107 /// @todo Convert to use the Rivet rotation matrix code (should be simpler) 00108 FourMomentum RotateAxes(const Rivet::FourMomentum& p, double M[3][3]){ 00109 double px_rot = M[0][0]*(p.px()) + M[0][1]*(p.py()) + M[0][2]*(p.pz()); 00110 double py_rot = M[1][0]*(p.px()) + M[1][1]*(p.py()) + M[1][2]*(p.pz()); 00111 double pz_rot = M[2][0]*(p.px()) + M[2][1]*(p.py()) + M[2][2]*(p.pz()); 00112 return FourMomentum(p.E(), px_rot, py_rot, pz_rot); 00113 } 00114 00115 // Untouched code from Lily 00116 /// @todo Convert to use the Rivet rotation matrix code (should be simpler) 00117 void CalcRotationMatrix(double nvec[3],double rot_mat[3][3]){ 00118 // clear momentum tensor 00119 for (size_t i = 0; i < 3; i++) { 00120 for (size_t j = 0; j < 3; j++) { 00121 rot_mat[i][j] = 0.; 00122 } 00123 } 00124 double mag3 = sqrt(nvec[0]*nvec[0] + nvec[1]*nvec[1]+ nvec[2]*nvec[2]); 00125 double mag2 = sqrt(nvec[0]*nvec[0] + nvec[1]*nvec[1]); 00126 /// @todo cout is not a valid response to a numerical error! Is the error condition reported?!? Assert added by AB for Rivet 1.8.2 00127 assert(mag3 > 0); 00128 if (mag3 <= 0) { 00129 cout << "rotation axis is null" << endl; 00130 return; 00131 } 00132 00133 double ctheta0 = nvec[2]/mag3; 00134 double stheta0 = mag2/mag3; 00135 double cphi0 = (mag2 > 0.) ? nvec[0]/mag2 : 0; 00136 double sphi0 = (mag2 > 0.) ? nvec[1]/mag2 : 0; 00137 00138 rot_mat[0][0] = -ctheta0*cphi0; 00139 rot_mat[0][1] = -ctheta0*sphi0; 00140 rot_mat[0][2] = stheta0; 00141 rot_mat[1][0] = sphi0; 00142 rot_mat[1][1] = -1.*cphi0; 00143 rot_mat[1][2] = 0.; 00144 rot_mat[2][0] = stheta0*cphi0; 00145 rot_mat[2][1] = stheta0*sphi0; 00146 rot_mat[2][2] = ctheta0; 00147 } 00148 00149 00150 /// Jet width calculation 00151 double getWidth(const Jet& jet) { 00152 const double phi_jet = jet.phi(); 00153 const double eta_jet = jet.eta(); 00154 double width(0), pTsum(0); 00155 foreach (const Particle& p, jet.particles()) { 00156 double pT = p.pT(); 00157 double eta = p.eta(); 00158 double phi = p.momentum().phi(); 00159 width += sqrt(pow(phi_jet - phi,2) + pow(eta_jet - eta, 2)) * pT; 00160 pTsum += pT; 00161 } 00162 const double rtn = (pTsum != 0.0) ? width/pTsum : -1; 00163 return rtn; 00164 } 00165 00166 00167 /// Eccentricity calculation, copied and adapted from Lily's code 00168 double getEcc(const Jet& jet) { 00169 vector<double> phis; 00170 vector<double> etas; 00171 vector<double> energies; 00172 00173 double etaSum(0), phiSum(0), eTot(0); 00174 foreach (const Particle& p, jet.particles()) { 00175 const double E = p.momentum().E(); 00176 const double eta = p.eta(); 00177 00178 energies.push_back(E); 00179 etas.push_back(jet.eta() - eta); 00180 00181 eTot += E; 00182 etaSum += eta * E; 00183 00184 /// @todo Replace with the Rivet deltaPhi function (or the mapAngleTo* functions) 00185 double dPhi = jet.momentum().phi() - p.momentum().phi(); 00186 //if DPhi does not lie within 0 < DPhi < PI take 2*PI off DPhi 00187 //this covers cases where DPhi is greater than PI 00188 if( fabs( dPhi - TWOPI ) < fabs(dPhi) ) dPhi -= TWOPI; 00189 //if DPhi does not lie within -PI < DPhi < 0 add 2*PI to DPhi 00190 //this covers cases where DPhi is less than -PI 00191 else if( fabs(dPhi + TWOPI) < fabs(dPhi) ) dPhi += TWOPI; 00192 phis.push_back(dPhi); 00193 00194 phiSum += dPhi * E; 00195 } 00196 00197 //these are the "pull" away from the jet axis 00198 etaSum = etaSum/eTot; 00199 phiSum = phiSum/eTot; 00200 00201 // now for every cluster we alter its position by moving it: 00202 // away from the new axis if it is in the direction of -ve pull 00203 // closer to the new axis if it is in the direction of +ve pull 00204 // the effect of this will be that the new energy weighted center will be on the old jet axis. 00205 double little_x(0), little_y(0); 00206 for (size_t k = 0; k < jet.particles().size(); ++k) { 00207 little_x+= etas[k]-etaSum; 00208 little_y+= phis[k]-phiSum; 00209 etas[k] = etas[k]-etaSum; 00210 phis[k] = phis[k]-phiSum; 00211 } 00212 00213 double x1(0), x2(0); 00214 for (size_t i = 0; i < jet.particles().size(); ++i) { 00215 x1 += 2. * energies[i]* etas[i] * phis[i]; // this is 2*X*Y 00216 x2 += energies[i]*(phis[i] * phis[i] - etas[i] * etas[i] ); // this is X^2 - Y^2 00217 } 00218 00219 // Variance calculations 00220 double theta = .5*atan2(x1, x2); 00221 double sinTheta =sin(theta); 00222 double cosTheta = cos(theta); 00223 double theta2 = theta + 0.5*PI; 00224 double sinThetaPrime = sin(theta2); 00225 double cosThetaPrime = cos(theta2); 00226 00227 double varX(0), varY(0); 00228 for (size_t i = 0; i < jet.particles().size(); i++) { 00229 const double x = sinTheta*etas[i] + cosTheta*phis[i]; 00230 const double y = sinThetaPrime*etas[i] + cosThetaPrime*phis[i]; 00231 varX += energies[i]* sqr(x); 00232 varY += energies[i]* sqr(y); 00233 } 00234 const double varianceMax = max(varX, varY); 00235 const double varianceMin = min(varX, varY); 00236 const double ecc = (varianceMax != 0.0) ? 1 - varianceMin/varianceMax : -1; 00237 return ecc; 00238 } 00239 00240 00241 /// Planar flow calculation, copied and adapted from Lily's code 00242 double getPFlow(const Jet& jet) { 00243 const double phi0 = jet.momentum().phi(); 00244 const double eta0 = jet.eta(); 00245 00246 double nref[3]; //< @todo 3-vector to rotate x to? Use Rivet vector classes 00247 nref[0] = cos(phi0)/cosh(eta0); 00248 nref[1] = sin(phi0)/cosh(eta0); 00249 nref[2] = tanh(eta0); 00250 00251 // Rotation matrix to align with nref 00252 double rotationMatrix[3][3]; 00253 CalcRotationMatrix(nref, rotationMatrix); 00254 00255 double iw00(0.), iw01(0.), iw11(0.), iw10(0.); 00256 foreach (const Particle& p, jet.particles()) { 00257 double a = 1./(p.momentum().E()*jet.momentum().mass()); 00258 FourMomentum rotclus = RotateAxes(p.momentum(), rotationMatrix); 00259 iw00 += a*pow(rotclus.px(), 2); 00260 iw01 += a*rotclus.px()*rotclus.py(); 00261 iw10 += a*rotclus.py()*rotclus.px(); 00262 iw11 += a*pow(rotclus.py(), 2); 00263 } 00264 00265 const double det = iw00*iw11 - iw01*iw10; 00266 const double trace = iw00 + iw11; 00267 00268 const double pf = (trace != 0.0) ? (4.0*det)/sqr(trace) : -1; 00269 return pf; 00270 } 00271 00272 00273 /// Angularity calculation, copied and adapted from Lily's code 00274 double getAngularity(const Jet& jet) { 00275 double sum_a = 0.; 00276 // a can take any value < 2 (e.g. 1,0,-0.5 etc) for infrared safety 00277 const double a = -2.; 00278 foreach (const Particle& p, jet.particles()) { 00279 double e_i = p.momentum().E(); 00280 double theta_i = jet.momentum().angle(p.momentum()); 00281 double e_theta_i = e_i * pow(sin(theta_i), a) * pow(1-cos(theta_i), 1-a); 00282 sum_a += e_theta_i; 00283 } 00284 const double rtn = (jet.momentum().mass() != 0.0 && !std::isnan(sum_a)) ? sum_a/jet.momentum().mass() : -1; 00285 return rtn; 00286 } 00287 00288 } 00289 00290 00291 } Generated on Tue May 13 2014 11:38:26 for The Rivet MC analysis system by ![]() |