ATLAS_2012_I1094564.cc
Go to the documentation of this file.
00001 // -*- C++ -*- 00002 #include "Rivet/Analysis.hh" 00003 #include "Rivet/Projections/FinalState.hh" 00004 #include "Rivet/Projections/FastJets.hh" 00005 #include "Rivet/Tools/BinnedHistogram.hh" 00006 00007 namespace Rivet { 00008 00009 00010 /// ATLAS jet substructure measurement 00011 class ATLAS_2012_I1094564 : public Analysis { 00012 public: 00013 00014 ATLAS_2012_I1094564() 00015 : Analysis("ATLAS_2012_I1094564") 00016 {} 00017 00018 00019 // Returns constituents to make it easier to do the filtering 00020 PseudoJets splitjet(fastjet::PseudoJet jet, double& last_R, const FastJets& fj, bool& unclustered) const { 00021 00022 // Build a new cluster sequence just using the constituents of this jet. 00023 fastjet::ClusterSequence cs(fj.clusterSeq()->constituents(jet), fastjet::JetDefinition(fastjet::cambridge_algorithm, M_PI/2.)); 00024 00025 // Get the jet back again 00026 vector<fastjet::PseudoJet> remadeJets = cs.inclusive_jets(0.); 00027 00028 if ( remadeJets.size() != 1 ) return remadeJets; 00029 00030 fastjet::PseudoJet remadeJet = remadeJets[0]; 00031 fastjet::PseudoJet parent1, parent2; 00032 unclustered = false; 00033 00034 while ( cs.has_parents(remadeJet, parent1, parent2) ) { 00035 if (parent1.squared_distance(parent2) < 0.09) break; 00036 if (parent1.m2() < parent2.m2()) { 00037 fastjet::PseudoJet tmp; 00038 tmp = parent1; parent1 = parent2; parent2 = tmp; 00039 } 00040 00041 double ktdist = parent1.kt_distance(parent2); 00042 double rtycut2 = 0.3*0.3; 00043 if (parent1.m() < 0.67*remadeJet.m() && ktdist > rtycut2*remadeJet.m2()) { 00044 unclustered = true; 00045 break; 00046 } else { 00047 remadeJet = parent1; 00048 } 00049 } 00050 00051 last_R = 0.5 * sqrt(parent1.squared_distance(parent2)); 00052 return cs.constituents(remadeJet); 00053 } 00054 00055 00056 fastjet::PseudoJet filterjet(PseudoJets jets, double& stingy_R, const double def_R) const { 00057 if (stingy_R == 0.0) stingy_R = def_R; 00058 stingy_R = def_R < stingy_R ? def_R : stingy_R; 00059 fastjet::JetDefinition stingy_jet_def(fastjet::cambridge_algorithm, stingy_R); 00060 fastjet::ClusterSequence scs(jets, stingy_jet_def); 00061 vector<fastjet::PseudoJet> stingy_jets = sorted_by_pt(scs.inclusive_jets(0)); 00062 fastjet::PseudoJet reconst_jet(0, 0, 0, 0); 00063 for (size_t isj = 0; isj < std::min((size_t) 3, stingy_jets.size()); ++isj) { 00064 reconst_jet += stingy_jets[isj]; 00065 } 00066 return reconst_jet; 00067 } 00068 00069 00070 // These are custom functions for n-subjettiness. 00071 PseudoJets jetGetAxes(int n_jets, const PseudoJets& inputJets, double subR) const { 00072 // Sanity check 00073 if (inputJets.size() < (size_t) n_jets) { 00074 MSG_ERROR("Not enough input particles."); 00075 return inputJets; 00076 } 00077 00078 // Get subjets, return 00079 fastjet::ClusterSequence sub_clust_seq(inputJets, fastjet::JetDefinition(fastjet::kt_algorithm, subR, fastjet::E_scheme, fastjet::Best)); 00080 return sub_clust_seq.exclusive_jets(n_jets); 00081 } 00082 00083 00084 double jetTauValue(double beta, double jet_rad, const PseudoJets& particles, const PseudoJets& axes, double Rcut) const { 00085 double tauNum = 0.0; 00086 double tauDen = 0.0; 00087 00088 if (particles.size() == 0) return 0.0; 00089 00090 for (size_t i = 0; i < particles.size(); i++) { 00091 // find minimum distance (set R large to begin) 00092 double minR = 10000.0; 00093 for (size_t j = 0; j < axes.size(); j++) { 00094 double tempR = sqrt(particles[i].squared_distance(axes[j])); 00095 if (tempR < minR) minR = tempR; 00096 } 00097 if (minR > Rcut) minR = Rcut; 00098 // calculate nominator and denominator 00099 tauNum += particles[i].perp() * pow(minR,beta); 00100 tauDen += particles[i].perp() * pow(jet_rad,beta); 00101 } 00102 00103 // return N-subjettiness (or 0 if denominator is 0) 00104 return safediv(tauNum, tauDen, 0); 00105 } 00106 00107 00108 void jetUpdateAxes(double beta, const PseudoJets& particles, PseudoJets& axes) const { 00109 vector<int> belongsto; 00110 for (size_t i = 0; i < particles.size(); i++) { 00111 // find minimum distance axis 00112 int assign = 0; 00113 double minR = 10000.0; 00114 for (size_t j = 0; j < axes.size(); j++) { 00115 double tempR = sqrt(particles[i].squared_distance(axes[j])); 00116 if (tempR < minR) { 00117 minR = tempR; 00118 assign = j; 00119 } 00120 } 00121 belongsto.push_back(assign); 00122 } 00123 00124 // iterative step 00125 double deltaR2, distphi; 00126 vector<double> ynom, phinom, den; 00127 00128 ynom.resize(axes.size()); 00129 phinom.resize(axes.size()); 00130 den.resize(axes.size()); 00131 00132 for (size_t i = 0; i < particles.size(); i++) { 00133 distphi = particles[i].phi() - axes[belongsto[i]].phi(); 00134 deltaR2 = particles[i].squared_distance(axes[belongsto[i]]); 00135 if (deltaR2 == 0.) continue; 00136 if (abs(distphi) <= M_PI) phinom.at(belongsto[i]) += particles[i].perp() * particles[i].phi() * pow(deltaR2, (beta-2)/2); 00137 else if ( distphi > M_PI) phinom.at(belongsto[i]) += particles[i].perp() * (-2 * M_PI + particles[i].phi()) * pow(deltaR2, (beta-2)/2); 00138 else if ( distphi < M_PI) phinom.at(belongsto[i]) += particles[i].perp() * (+2 * M_PI + particles[i].phi()) * pow(deltaR2, (beta-2)/2); 00139 ynom.at(belongsto[i]) += particles[i].perp() * particles[i].rap() * pow(deltaR2, (beta-2)/2); 00140 den.at(belongsto[i]) += particles[i].perp() * pow(deltaR2, (beta-2)/2); 00141 } 00142 00143 // reset to new axes 00144 for (size_t j = 0; j < axes.size(); j++) { 00145 if (den[j] == 0.) axes.at(j) = axes[j]; 00146 else { 00147 double phi_new = fmod( 2*M_PI + (phinom[j] / den[j]), 2*M_PI ); 00148 double pt_new = axes[j].perp(); 00149 double y_new = ynom[j] / den[j]; 00150 double px = pt_new * cos(phi_new); 00151 double py = pt_new * sin(phi_new); 00152 double pz = pt_new * sinh(y_new); 00153 axes.at(j).reset(px, py, pz, axes[j].perp()/2); 00154 } 00155 } 00156 } 00157 00158 00159 void init() { 00160 00161 /// Projections: 00162 FinalState fs(-4.5, 4.5, 0.*GeV); 00163 addProjection(fs, "FS"); 00164 addProjection(FastJets(fs, FastJets::ANTIKT, 1.0), "AKT"); 00165 addProjection(FastJets(fs, FastJets::CAM, 1.2) , "CA" ); 00166 00167 /// Histograms: 00168 _h_camass.addHistogram(200, 300, bookHisto1D(1, 1, 1)); 00169 _h_camass.addHistogram(300, 400, bookHisto1D(2, 1, 1)); 00170 _h_camass.addHistogram(400, 500, bookHisto1D(3, 1, 1)); 00171 _h_camass.addHistogram(500, 600, bookHisto1D(4, 1, 1)); 00172 00173 _h_filtmass.addHistogram(200, 300, bookHisto1D(5, 1, 1)); 00174 _h_filtmass.addHistogram(300, 400, bookHisto1D(6, 1, 1)); 00175 _h_filtmass.addHistogram(400, 500, bookHisto1D(7, 1, 1)); 00176 _h_filtmass.addHistogram(500, 600, bookHisto1D(8, 1, 1)); 00177 00178 _h_ktmass.addHistogram(200, 300, bookHisto1D( 9, 1, 1)); 00179 _h_ktmass.addHistogram(300, 400, bookHisto1D(10, 1, 1)); 00180 _h_ktmass.addHistogram(400, 500, bookHisto1D(11, 1, 1)); 00181 _h_ktmass.addHistogram(500, 600, bookHisto1D(12, 1, 1)); 00182 00183 _h_ktd12.addHistogram(200, 300, bookHisto1D(13, 1, 1)); 00184 _h_ktd12.addHistogram(300, 400, bookHisto1D(14, 1, 1)); 00185 _h_ktd12.addHistogram(400, 500, bookHisto1D(15, 1, 1)); 00186 _h_ktd12.addHistogram(500, 600, bookHisto1D(16, 1, 1)); 00187 00188 _h_ktd23.addHistogram(200, 300, bookHisto1D(17, 1 ,1)); 00189 _h_ktd23.addHistogram(300, 400, bookHisto1D(18, 1 ,1)); 00190 _h_ktd23.addHistogram(400, 500, bookHisto1D(19, 1 ,1)); 00191 _h_ktd23.addHistogram(500, 600, bookHisto1D(20, 1 ,1)); 00192 00193 _h_cat21.addHistogram(200, 300, bookHisto1D(21, 1, 1)); 00194 _h_cat21.addHistogram(300, 400, bookHisto1D(22, 1, 1)); 00195 _h_cat21.addHistogram(400, 500, bookHisto1D(23, 1, 1)); 00196 _h_cat21.addHistogram(500, 600, bookHisto1D(24, 1, 1)); 00197 00198 _h_cat32.addHistogram(200, 300, bookHisto1D(25, 1, 1)); 00199 _h_cat32.addHistogram(300, 400, bookHisto1D(26, 1, 1)); 00200 _h_cat32.addHistogram(400, 500, bookHisto1D(27, 1, 1)); 00201 _h_cat32.addHistogram(500, 600, bookHisto1D(28, 1, 1)); 00202 00203 _h_ktt21.addHistogram(200, 300, bookHisto1D(29, 1, 1)); 00204 _h_ktt21.addHistogram(300, 400, bookHisto1D(30, 1, 1)); 00205 _h_ktt21.addHistogram(400, 500, bookHisto1D(31, 1, 1)); 00206 _h_ktt21.addHistogram(500, 600, bookHisto1D(32, 1, 1)); 00207 00208 _h_ktt32.addHistogram(200, 300, bookHisto1D(33, 1, 1)); 00209 _h_ktt32.addHistogram(300, 400, bookHisto1D(34, 1, 1)); 00210 _h_ktt32.addHistogram(400, 500, bookHisto1D(35, 1, 1)); 00211 _h_ktt32.addHistogram(500, 600, bookHisto1D(36, 1, 1)); 00212 } 00213 00214 00215 /// Perform the per-event analysis 00216 void analyze(const Event& event) { 00217 const double weight = event.weight(); 00218 00219 using namespace fastjet; 00220 00221 // Get anti-kt jets with p_T > 200 GeV, check abs(y) < 2, and fill mass histograms 00222 const FastJets& ktfj = applyProjection<FastJets>(event, "AKT"); 00223 PseudoJets ktjets = ktfj.pseudoJetsByPt(200*GeV); 00224 foreach (const PseudoJet ajet, ktjets) { 00225 if (abs(ajet.rap()) < 2) { 00226 _h_ktmass.fill(ajet.perp(), ajet.m(), weight); 00227 } 00228 } 00229 00230 // Same as above but C/A jets 00231 const FastJets& cafj = applyProjection<FastJets>(event, "CA"); 00232 PseudoJets cajets = cafj.pseudoJetsByPt(200*GeV); 00233 foreach (const PseudoJet ajet, cajets) { 00234 if (abs(ajet.rap()) < 2) { 00235 _h_camass.fill(ajet.perp(), ajet.m(), weight); 00236 } 00237 } 00238 00239 // Split and filter. 00240 // Only do this to C/A jets in this analysis. 00241 foreach (const PseudoJet pjet, cajets) { 00242 if ( pjet.perp() > 600 || abs(pjet.rap()) > 2) continue; 00243 double dR = 0; 00244 bool unclustered = false; 00245 PseudoJets split_jets = splitjet(pjet, dR, cafj, unclustered); 00246 if ( (dR < 0.15) || (unclustered == false) ) continue; 00247 PseudoJet filt_jet = filterjet(split_jets, dR, 0.3); 00248 _h_filtmass.fill(filt_jet.perp(), filt_jet.m(), weight); 00249 } 00250 00251 // Use the two last stages of clustering to get sqrt(d_12) and sqrt(d_23). 00252 // Only use anti-kt jets in this analysis. 00253 foreach (const PseudoJet pjet, ktjets) { 00254 if (pjet.perp() > 600 || abs(pjet.rap()) > 2) continue; 00255 ClusterSequence subjet_cseq(ktfj.clusterSeq()->constituents(pjet), JetDefinition(kt_algorithm, M_PI/2.)); 00256 double d_12 = subjet_cseq.exclusive_dmerge(1) * M_PI*M_PI/4.; 00257 double d_23 = subjet_cseq.exclusive_dmerge(2) * M_PI*M_PI/4.; 00258 _h_ktd12.fill(pjet.perp(), sqrt(d_12), weight); 00259 _h_ktd23.fill(pjet.perp(), sqrt(d_23), weight); 00260 } 00261 00262 // N-subjettiness, use beta = 1 (no rationale given). 00263 // Uses the functions defined above. 00264 // C/A jets first, anti-kt after. 00265 double beta = 1.; 00266 //Rcut is used for particles that are very far from the closest axis. At 10 00267 //is has no impact on the outcome of the calculation 00268 double Rcut = 10.; 00269 foreach (const PseudoJet pjet, cajets) { 00270 if (pjet.perp() > 600*GeV || fabs(pjet.rap()) > 2) continue; 00271 00272 const PseudoJets constituents = cafj.clusterSeq()->constituents(pjet); 00273 if (constituents.size() < 3) continue; 00274 00275 const PseudoJets axis1 = jetGetAxes(1, constituents, M_PI/2.0); 00276 const PseudoJets axis2 = jetGetAxes(2, constituents, M_PI/2.0); 00277 const PseudoJets axis3 = jetGetAxes(3, constituents, M_PI/2.0); 00278 00279 const double radius = 1.2; 00280 const double tau1 = jetTauValue(beta, radius, constituents, axis1, Rcut); 00281 const double tau2 = jetTauValue(beta, radius, constituents, axis2, Rcut); 00282 const double tau3 = jetTauValue(beta, radius, constituents, axis3, Rcut); 00283 00284 if (tau1 == 0 || tau2 == 0) continue; 00285 _h_cat21.fill(pjet.perp(), tau2/tau1, weight); 00286 _h_cat32.fill(pjet.perp(), tau3/tau2, weight); 00287 } 00288 00289 foreach (const PseudoJet pjet, ktjets) { 00290 if (pjet.perp() > 600*GeV || fabs(pjet.rap()) > 2) continue; 00291 00292 const PseudoJets constituents = ktfj.clusterSeq()->constituents(pjet); 00293 if (constituents.size() < 3) continue; 00294 00295 const PseudoJets axis1 = jetGetAxes(1, constituents, M_PI/2.0); 00296 const PseudoJets axis2 = jetGetAxes(2, constituents, M_PI/2.0); 00297 const PseudoJets axis3 = jetGetAxes(3, constituents, M_PI/2.0); 00298 00299 const double radius = 1.0; 00300 const double tau1 = jetTauValue(beta, radius, constituents, axis1, Rcut); 00301 const double tau2 = jetTauValue(beta, radius, constituents, axis2, Rcut); 00302 const double tau3 = jetTauValue(beta, radius, constituents, axis3, Rcut); 00303 if (tau1 == 0 || tau2 == 0) continue; 00304 00305 _h_ktt21.fill(pjet.perp(), tau2/tau1, weight); 00306 _h_ktt32.fill(pjet.perp(), tau3/tau2, weight); 00307 } 00308 } 00309 00310 00311 /// Normalise histograms etc., after the run 00312 void finalize() { 00313 foreach (Histo1DPtr h, _h_camass.getHistograms()) normalize(h); 00314 foreach (Histo1DPtr h, _h_filtmass.getHistograms()) normalize(h); 00315 foreach (Histo1DPtr h, _h_ktmass.getHistograms()) normalize(h); 00316 foreach (Histo1DPtr h, _h_ktd12.getHistograms()) normalize(h); 00317 foreach (Histo1DPtr h, _h_ktd23.getHistograms()) normalize(h); 00318 foreach (Histo1DPtr h, _h_cat21.getHistograms()) normalize(h); 00319 foreach (Histo1DPtr h, _h_cat32.getHistograms()) normalize(h); 00320 foreach (Histo1DPtr h, _h_ktt21.getHistograms()) normalize(h); 00321 foreach (Histo1DPtr h, _h_ktt32.getHistograms()) normalize(h); 00322 } 00323 00324 private: 00325 00326 BinnedHistogram<double> _h_camass; 00327 BinnedHistogram<double> _h_filtmass; 00328 BinnedHistogram<double> _h_ktmass; 00329 BinnedHistogram<double> _h_ktd12; 00330 BinnedHistogram<double> _h_ktd23; 00331 BinnedHistogram<double> _h_cat21; 00332 BinnedHistogram<double> _h_cat32; 00333 BinnedHistogram<double> _h_ktt21; 00334 BinnedHistogram<double> _h_ktt32; 00335 00336 }; 00337 00338 00339 // The hook for the plugin system 00340 DECLARE_RIVET_PLUGIN(ATLAS_2012_I1094564); 00341 00342 } Generated on Wed Oct 7 2015 12:09:10 for The Rivet MC analysis system by ![]() |